Javaでメモリリークを作成するにはどうすればいいですか? 質問する

Javaでメモリリークを作成するにはどうすればいいですか? 質問する

先ほど面接があり、Java でメモリ リークを作成するように求められました。

言うまでもなく、どうやって作り始めればいいのか全くわからず、とてもバカな気分になりました。

例は何でしょうか?

ベストアンサー1

純粋な Java で真のメモリ リーク (実行中のコードではアクセスできないが、メモリ内にまだ保存されているオブジェクト) を作成するための良い方法を次に示します。

  1. アプリケーションは長時間実行されるスレッドを作成します (または、スレッド プールを使用してさらに高速にリークします)。
  2. スレッドは (オプションでカスタム) を介してクラスをロードしますClassLoader
  3. クラスは大量のメモリ (例new byte[1000000]) を割り当て、そのメモリへの強い参照を静的フィールドに格納し、次に自分自身への参照を に格納しますThreadLocal。追加のメモリを割り当てるかどうかはオプションですが (クラス インスタンスをリークするだけで十分)、割り当てるとリークの処理がそれだけ高速化されます。
  4. アプリケーションは、カスタム クラスまたはそのClassLoaderロード元へのすべての参照をクリアします。
  5. 繰り返す。

Oracle の JDK での実装方法によりThreadLocal、メモリ リークが発生します。

  • それぞれにThreadプライベート フィールドがありthreadLocals、実際にスレッド ローカルの値が格納されます。
  • このマップ内の各キーはオブジェクトへの弱参照であるThreadLocalため、そのThreadLocalオブジェクトがガベージコレクションされた後、そのエントリはマップから削除されます。
  • ただし、各値は強い参照であるため、値が (直接的または間接的に)ThreadLocalそのキーであるオブジェクトを指している場合、スレッドが存続する限り、そのオブジェクトはガベージ コレクションされることも、マップから削除されることもありません。

この例では、強い参照のチェーンは次のようになります。

Threadオブジェクト →threadLocalsマップ → サンプル クラスのインスタンス → サンプル クラス → 静的ThreadLocalフィールド →ThreadLocalオブジェクト。

( はClassLoader実際にはリークの作成には関与していませんが、追加の参照チェーン (例のクラス → ClassLoader→ ロードされたすべてのクラス) によってリークが悪化するだけです。多くの JVM 実装では、特に Java 7 より前のバージョンでは、クラスとClassLoaderが permgen に直接割り当てられ、ガベージ コレクションがまったく行われなかったため、状況はさらに悪化していました。)

このパターンのバリエーションは、何らかの方法で自分自身を指す を使用するアプリケーションを頻繁に再デプロイすると、アプリケーション コンテナー (Tomcat など) がメモリを大量にリークする可能性がある理由ですThreadLocal。これは、いくつかの微妙な理由で発生する可能性があり、デバッグや修正が困難な場合がよくあります。

更新:多くの人がそれを要求し続けているから、この動作を実際に示すサンプルコードを以下に示します。

おすすめ記事