4

jvisualvmアプリケーションのメモリリークをチェックするために使用しています。ヒープダンプを実行すると、ガベージコレクションされているはずのいくつかのオブジェクトが開いたままになっていることがあります。

それらに対して「ShowNearestGCRoot」コマンドを実行すると、ルートが、Runnableインターフェイスを実装する定義済みのクラスであることが示されます。参照はとしてリストされていますが(java frame)、これはスレッド化と関係があることを私は知っています。このノードのツリーを展開すると、ツリーが開いて表示されます<no references>。したがって、これは私が開いたままにしている参照ではなく、Javaの内部にあるものであることは明らかです。

jvisualvmにリストされているGCRootオブジェクトは、タイプAnalyticNode extends NodeがですNode implements Runnable。このルートオブジェクトは、「フレーム」という言葉が使用されているにもかかわらず、AWT、Swing、またはヘビーウェイトのユーザーインターフェイスコンポーネントとはまったく関係がありません。この場合、「フレーム」という言葉はスレッディングを指します。

では、Javaは、これを開いたままにする最後のRunnableへの参照をどこかに保持しますか?ヒープダンプのために適切にガベージコレクションできるように、この参照を解放するようにJavaに指示する方法はありますか?

何が起きてる?

4

2 に答える 2

7

このコンテキストでは、「フレーム」はスタックフレームを指します。Runnable実行中のスレッドのターゲットになる代わりに(またはそれに加えて)、実行中のスレッドのスタック上のフレームのローカル変数に格納されているように聞こえます。フレームに関連付けられたメソッドが戻ると、収集の対象になります。


Runnableその後のコメントに基づくと、カスタムスレッドプールには、が割り当てられているローカル変数があると思います。スコープが大きすぎて(ループの外側)、ループをnull繰り返すたびにクリア(割り当て)されていない可能性があります。

ワーカースレッドで次のようなコードで記述されているものと一致する状況を再現できます。

Runnable target = null;
while (true) {
  target = queue.take();
  target.run();
}

の宣言をクリーンアップしtargetてループ内に配置すると、問題が修正されます。

コアJavaから実装に切り替えるExecutorか、修正したい場合はカスタムスレッドプールの関連コードを投稿することをお勧めします。

于 2011-10-27T18:12:01.977 に答える
1

作成したオブジェクトをどのように処理しましたか?スレッドを作成してポイントしましたか?その場合、run()のコードの実行を終了させて​​、スレッドが停止していることを確認する必要があります。

于 2011-10-27T18:09:00.143 に答える