ガベージコレクションのルーツは何ですか?
ルートの定義を「プログラムがアクセスできる任意の参照」と読みました。ライブの定義は、使用されているオブジェクトであり、ローカル変数、静的変数の場合があります。
ルートオブジェクトとライブオブジェクトの違いを区別することとは少し混乱しています。
ルートへのパスとは何ですか?ルートオブジェクトとライブオブジェクトはどのように機能しますか?
誰かが詳しく説明できますか?
ガベージコレクションのルーツは何ですか?
ルートの定義を「プログラムがアクセスできる任意の参照」と読みました。ライブの定義は、使用されているオブジェクトであり、ローカル変数、静的変数の場合があります。
ルートオブジェクトとライブオブジェクトの違いを区別することとは少し混乱しています。
ルートへのパスとは何ですか?ルートオブジェクトとライブオブジェクトはどのように機能しますか?
誰かが詳しく説明できますか?
メモリ内のオブジェクトをツリーと考えると、「ルート」はルートノードになります。つまり、プログラムからすぐにアクセスできるすべてのオブジェクトです。
Person p = new Person();
p.car = new Car(RED);
p.car.engine = new Engine();
p.car.horn = new AnnoyingHorn();
4つのオブジェクトがあります。人、赤い車、そのエンジンとホーン。参照グラフを描画します。
Person [p]
|
Car (red)
/ \
Engine AnnoyingHorn
そして、あなたはPerson
木の「根」にたどり着くでしょう。プログラムがオブジェクトp
を参照するためにいつでも使用する可能性のあるローカル変数によって参照されるため、ライブです。これは、、などを介して、Person
他のオブジェクトにも当てはまります。p.car
p.car.engine
再帰的に接続されている他のすべてのオブジェクトはライブであるためPerson
、GCがそれらを収集すると問題が発生します。
ただし、しばらくしてから次のコマンドを実行する場合は、次のことを考慮してください。
p.car = new Car(BLUE);
そして、グラフを再描画します。
Person [p]
|
Car (blue) Car (red)
/ \
Engine AnnoyingHorn
これで、はを介してアクセスでき、青い車はを介してPerson
アクセスできますが、赤い車またはそのパーツに再びアクセスする方法はありません。ライブルートに接続されていません。安全に回収できます。p
p.car
したがって、実際には、すべての開始点(すべてのローカル変数、グローバル、静的、他のスレッドおよびスタックフレーム内のすべて)、すべてのルートを取得し、すべての参照を再帰的に追跡して、すべての「ライブ」オブジェクトのリストを作成する必要があります。使用中で削除に適さないオブジェクト。他のすべてはゴミであり、収集されるのを待っています。
GC(ガベージコレクター)ルートは、ガベージコレクター専用のオブジェクトです。ガベージコレクタは、GCルートではなく、GCルートからの参照によってアクセスできないオブジェクトを収集します。
GCルートにはいくつかの種類があります。1つのオブジェクトが複数の種類のルートに属することができます。ルートの種類は次のとおりです。
( YourKitのWebサイトへのクレジット)
YourKitが言及していないのは、GCがfinalize()
メソッドを実行するまで、ファイナライズを待機しているオブジェクトがルートとして保持されるという事実です。これにより、予想外に大きなグラフが一時的に保持される可能性があります。一般的な経験則では、ファイナライザーを使用しないことです(ただし、これは別の質問です)。
ルートまたはガベージコレクションのルートは、常に到達可能なオブジェクトです。オブジェクトが常に到達可能である場合、そのオブジェクトはガベージコレクションの対象にはなりません。したがって、ルートは常に収集の対象外です。これは、ヒープ上の他のすべてのオブジェクトの到達可能性が決定されるオブジェクトの初期セットです。
ガベージコレクションのルートから到達可能なヒープ上の他のオブジェクトは、ライブオブジェクトと見なされ、コレクションの対象外です。到達不能なオブジェクトは、再利用のマークを付けることができます。
私は.NetプラットフォームよりもJavaをよく知っているので、1つだけ話します。Javaプラットフォームでは、GCルートは実際には実装に依存します。ただし、ほとんどのランタイムでは、GCルートはスタック上のオペランド(現在スレッドで使用されているため)およびクラスのクラス(静的)メンバーになる傾向があります。到達可能性は、ほとんどのJVMでこれらのオブジェクトから計算されます。JNI呼び出しで使用されるローカルパラメータとオペランドがルートセットの一部と見なされ、到達可能性の計算にも使用される場合もあります。
これにより、ルート(セット)とは何か、ライブオブジェクトとは何かについての長引く疑問が解消されることを願っています。
IBM Webサイトには、GCルートとして以下がリストされています。
これらのいくつかはメモリアナライザーによって行われる人工的な構成ですが、ヒープダンプを見ている場合は注意することが重要です。
システムクラス
ブートストラップローダーまたはシステムクラスローダーによってロードされたクラス。たとえば、このカテゴリには、java.util。*パッケージのクラスなど、rt.jarファイル(Javaランタイム環境の一部)のすべてのクラスが含まれます。
JNIローカル
ネイティブコードのローカル変数。たとえば、ユーザー定義のJNIコードやJVM内部コード。
JNIグローバル
ネイティブコードのグローバル変数。たとえば、ユーザー定義のJNIコードやJVM内部コード。
スレッドブロック
アクティブなスレッドブロックから参照されたオブジェクト。
スレッド
実行中のスレッド。
ビジーモニター
wait()またはnotify()メソッドを呼び出したもの、または同期されたものすべて。たとえば、synchronized(Object)メソッドを呼び出すか、同期されたメソッドを入力します。メソッドが静的である場合、ルートはクラスです。それ以外の場合、ルートはオブジェクトです。
Javaローカル
ローカル変数。たとえば、入力パラメータ、またはスレッドのスタックに残っているメソッドのローカルで作成されたオブジェクト。ネイティブスタック
ユーザー定義のJNIコードやJVM内部コードなどのネイティブコードの入力または出力パラメーター。多くのメソッドにはネイティブ部分があり、メソッドパラメーターとして処理されるオブジェクトはガベージコレクションのルートになります。たとえば、ファイル、ネットワーク、I / O、またはリフレクション操作に使用されるパラメーター。
ファイナライザー
キューにあり、ファイナライザーの実行を待機しているオブジェクト。
未完成
ファイナライズメソッドがありますが、ファイナライズされておらず、ファイナライザキューにまだ存在しないオブジェクト。
到達不能
他のルートから到達できないオブジェクトですが、オブジェクトを分析に含めることができるように、MemoryAnalyzerによってルートとしてマークされています。
到達不能なオブジェクトは、多くの場合、ガベージコレクションアルゴリズムの最適化の結果です。たとえば、オブジェクトがガベージコレクションの候補になる可能性がありますが、ガベージコレクションプロセスが高額になるほど小さい場合があります。この場合、オブジェクトはガベージコレクションされない可能性があり、到達不能オブジェクトとして残る可能性があります。
デフォルトでは、Memory Analyzerがヒープダンプを解析するときに、到達不能なオブジェクトは除外されます。したがって、これらのオブジェクトは、ヒストグラム、ドミネーターツリー、またはクエリ結果には表示されません。この動作を変更するには、「ファイル」>「設定...」>「Java用IBM診断ツール-メモリー・アナライザー」をクリックし、「到達不能オブジェクトを保持」チェック・ボックスを選択します。
Javaスタックフレーム
ローカル変数を保持するJavaスタックフレーム。このタイプのガベージコレクションルートは、Javaスタックフレームをオブジェクトとして扱うようにプリファレンスを設定した場合にのみ生成されます。詳細については、「Javaの基本:スレッドとスレッドスタッククエリ」を参照してください。
わからない
ルートタイプが不明なオブジェクト。IBM Portable Heap Dump(.phd)ファイルなどの一部のダンプには、ルート情報がありません。この場合、Memory Analyzerパーサーは、インバウンド参照がないオブジェクト、または他のルートから到達できないオブジェクトを不明としてマークします。このアクションにより、MemoryAnalyzerがダンプ内のすべてのオブジェクトを確実に保持します。
Javaでは、スレッドがルートオブジェクトであると言えます。すべてのライブオブジェクトは、ライブスレッドにバックトレースできます。たとえば、静的オブジェクトは、クラスローダーによって参照されるクラスによって参照されます。クラスローダーは、そのクラスのインスタンスによって参照される別のクラスによって参照されます。...参照されるRunnableによって参照されます。ライブスレッドによって。(クラスはGCすることができ、ルートにすることはできません)
すべてのスレッドの「実際の」ルートを検討することもできますが、これは標準のJavaの領域から外れています。それが何であるか、そしてそれがどのようにすべてのスレッドを参照するかを言うことはできません。