50

複雑で循環的な方法で相互に参照するクラス インスタンスの集合体を考えると、ガベージ コレクターがこれらのオブジェクトを解放できない可能性はありますか?

これは過去に JVM の問題だったことを漠然と思い出しますが、これは何年も前に解決されたと思っていました。それでも、jhat を調査したところ、現在直面しているメモリ リークの原因が循環参照であることが明らかになりました。

注: 私は常に、JVM が循環参照を解決し、そのような「ゴミの島」をメモリから解放できるという印象を受けてきました。ただし、誰かが例外を見つけたかどうかを確認するために、この質問を投げかけています。

4

10 に答える 10

42

循環参照で問題が発生するのは、非常に単純な実装だけです。ウィキペディアには、さまざまな GC アルゴリズムに関する優れた記事があります。さらに詳しく知りたい場合は、 (Amazon) Garbage Collection: Algorithms for Automatic Dynamic Memory Management を試してください。Java には 1.2 から優れたガベージ コレクターがあり、1.5 と Java 6 では非常に優れたガベージ コレクターがありました。

GC を改善するための難しい部分は、一時停止とオーバーヘッドを削減することであり、循環参照のような基本的なことではありません。

于 2008-10-07T00:11:53.620 に答える
23

ガベージ コレクターは、ルート オブジェクトがどこにあるかを認識しています: 静的オブジェクト、スタック上のローカル オブジェクトなど。オブジェクトがルートから到達できない場合、オブジェクトは再利用されます。彼らが到達可能な場合、彼らは固執する必要があります。

于 2008-10-07T00:02:47.320 に答える
12

ライアン、 Java の循環参照へのコメントから判断すると、おそらくブートストラップ/システム クラスローダーによってロードされたクラスからオブジェクトを参照するという罠に陥りました。すべてのクラスは、クラスをロードしたクラスローダによって参照されるため、クラスローダにアクセスできなくなった場合にのみ、ガベージ コレクションを実行できます。問題は、ブートストラップ/システム クラスローダがガベージ コレクションされないことです。したがって、システム クラスローダによってロードされたクラスから到達可能なオブジェクトもガベージ コレクションできません。

この動作の理由は、JLS で説明されています。たとえば、Third Edition 12.7 http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.7です。

于 2008-10-07T18:31:42.670 に答える
4

私の記憶が正しければ、仕様によると、JVM が収集できるものではなく、収集できないもの (到達可能なもの)についてのみ保証されます。

リアルタイム JVM を使用している場合を除き、最新のガベージ コレクターのほとんどは、複雑な参照構造を処理し、安全に削除できる「サブグラフ」を識別できるはずです。より多くの研究アイデアが (研究ではなく) 標準 VM に組み込まれるにつれて、これを行う効率、待ち時間、および可能性は時間の経過とともに改善されます。

于 2008-10-07T00:35:31.983 に答える
3

Java 仕様によると、ガベージ コレクターは、どのスレッドからもアクセスできない場合にのみ、オブジェクトをガベージ コレクションできます。

到達可能とは、A から B につながる参照、または参照のチェーンが存在し、C、D、...Z を介してすべてを処理できることを意味します。

2000 年以来、JVM が収集しないことは私にとって問題ではありませんでしたが、マイレージは異なる場合があります。

ヒント: Java シリアライゼーションはオブジェクトをキャッシュして、オブジェクト メッシュの転送を効率化します。大きな一時的なオブジェクトが多数あり、すべてのメモリが占​​有されている場合は、シリアライザーをリセットしてキャッシュをクリアします。

于 2008-10-07T00:27:24.683 に答える
3

いいえ、少なくとも Sun の公式 JVM を使用すると、ガベージ コレクターはこれらのサイクルを検出し、外部からの参照がなくなるとすぐにメモリを解放できます。

于 2008-10-07T00:02:55.013 に答える
2

すでに言われていることを増幅するだけです:

私が 6 年間取り組んできたアプリケーションは、最近 Java 1.4 から Java 1.6 に変更され、以前はガベージ コレクションが可能であることさえ認識していなかったものへの静的参照を追加する必要があることがわかりました。以前はガベージ コレクターがうまく機能しなかったため、静的参照は必要ありませんでしたが、現在ははるかに優れています。

于 2008-10-07T00:10:54.373 に答える
2

参照カウント GC は、この問題で有名です。特に、Suns JVM は参照カウント GC を使用しません。

ヒープのルートからオブジェクトに到達できない場合 (通常、最低でもクラスローダーを介して、他に何もなければ、オブジェクトは破棄されます。これは、通常の Java GC 中に新しいヒープにオブジェクトがコピーされないためです。

于 2008-10-07T00:20:52.277 に答える
0

ガベージ コレクターは非常に洗練されたソフトウェアであり、巨大な JCK テスト スイートでテストされています。完璧ではありませんが、Java コンパイラ (javac) がすべてのクラスをコンパイルし、JVM がそれをインスタンス化する限り、うまくいく可能性が非常に高くなります。

繰り返しますが、このオブジェクト グラフのルートへの参照を保持している場合、メモリは解放されませんが、自分が何をしているのかわかっていれば問題ありません。

于 2008-10-07T00:02:54.903 に答える