1. ホーム
  2. java

[解決済み] Javaでメモリーリークを発生させるにはどうしたらいいですか?

2022-03-18 13:19:20

質問

を作成するように言われました。 メモリリーク Javaで

もちろん、どうやって作ればいいのか、まったくわからない状態だったのは言うまでもありません。

例えばどんなことでしょうか?

どのように解決するのですか?

純粋なJavaで真のメモリーリーク(実行中のコードからはアクセスできないが、メモリーには保存されているオブジェクト)を作り出す良い方法を紹介します。

  1. アプリケーションが長時間稼働するスレッドを作成する(あるいはスレッドプールを使ってさらに高速にリークする)。
  2. スレッドは、(オプションでカスタムの) ClassLoader .
  3. クラスが大きなメモリチャンクを確保する(例えば new byte[1000000] )、それへの強い参照を静的フィールドに格納し、自分自身への参照を ThreadLocal . 余分なメモリの確保は任意ですが(クラスインスタンスのリークで十分です)、リークの動作がそれだけ速くなります。
  4. アプリケーションはカスタムクラスへのすべての参照を消去するか、または ClassLoader からロードされた。
  5. 繰り返してください。

方法によるもの ThreadLocal が Oracle の JDK で実装されているため、メモリリークが発生します。

  • Thread はプライベートフィールド threadLocals で、実際にスレッドローカルの値を格納する。
  • それぞれの キー への弱い参照である。 ThreadLocal オブジェクトが作成されるので、その後に ThreadLocal オブジェクトがゴミとして回収されると、そのエントリはマップから削除されます。
  • しかし、各 は強い参照なので、ある値が (直接または間接的に) ThreadLocal オブジェクトを作成します。 キー そのスレッドが生きている限り、そのオブジェクトはガベージコレクトされることも、マップから削除されることもない。

この例では、強い参照の連鎖は次のようになります。

Thread オブジェクト → threadLocals map → exampleクラスのインスタンス → exampleクラス → static ThreadLocal フィールド → ThreadLocal オブジェクトを作成します。

(その ClassLoader は、実際にはリークを発生させる役割を果たさず、 この追加の参照チェーンのためにリークを悪化させるだけです。 ClassLoader →読み込んだ全てのクラス 特にJava 7以前の多くのJVMの実装では、さらに悪いことに、クラスと ClassLoader はそのままpermgenに割り当てられ、ガベージコレクトされることは全くありませんでした)。

このパターンのバリエーションとして、アプリケーションコンテナ(Tomcatなど)で、たまたま ThreadLocal が、何らかの形で自分自身を指しているのです。これは多くの微妙な理由で発生する可能性があり、しばしばデバッグや修正が困難です。

更新情報 : たくさんの方からご要望をいただいているので この動作を示すサンプルコードを以下に示します。 .