JVMインタビューレビューシリーズ:JVMガベージコレクション中にガベージを決定する方法は?GCルートとは何か知っていますか

JVMインタビューの要約

JVMガベージコレクション中にガベージを決定する方法は?GCルートとは何か知っていますか

ごみとは

簡単に言えば、使用されなくなったメモリ内のスペースはゴミです

オブジェクトがリサイクルできるかどうかを判断する方法

参照カウント

Javaでは、参照とオブジェクトは関連しています。オブジェクトを操作する場合は、参照を使用する必要があります。

したがって、簡単な方法は、参照カウントによってオブジェクトをリサイクルできるかどうかを判断することであることは明らかです。簡単に言えば、オブジェクトに参照カウンターを追加します

それを参照する場所があるときはいつでも、カウンター値は1ずつ増加します。

参照が失敗するたびに、カウンター値は1ずつ減少します。

カウンタ値がゼロのオブジェクトは使用できなくなり、このオブジェクトはリサイクル可能なオブジェクトになります。

では、なぜこの方法が主流のJava仮想マシンで使用されないのでしょうか。主な理由は、オブジェクト間の循環参照の問題を解決することが難しいためです。

このアルゴリズムは存在しますが、現時点では誰も使用しておらず、循環参照の問題を解決することはできません。理解してください。

画像-20200318213301603

到達可能性分析のためにルートノードを列挙します

ルート検索パスアルゴリズム

参照カウント方法の循環参照問題を解決するために、Javaは到達可能性分析の方法を使用します。

画像-20200319113611244

いわゆるGCルートまたはトレースルートの「ルートセット」は、アクティブである必要がある参照のセットです。

基本的な考え方は、GC Rootsという名前の一連のオブジェクトを開始点として使用し、GC Rootsと呼ばれるこのオブジェクトから開始して、下方向に検索することです。オブジェクトが参照チェーンによってGC Rootsに接続されていない場合、このオブジェクトは利用不可。つまり、ルートとして一連の参照が与えられた場合、参照関係を介してオブジェクトグラフをトラバースし、トラバースできる(到達可能)オブジェクトは生きていると判断され、トラバースされていないオブジェクトは死んでいると判断されます。

画像-20200319114526625

ルートディレクトリであるLinux /に似たGCRootsオブジェクトから始める必要があります

青い部分はGCRootsから始まり、周期的に到達可能です。

GCRootsから始まる白い部分には到達できません

一文でGCのルーツを理解する

人間、犬、セーターの3つのエンティティがあるとします。

そして、彼らの関係は、人々が犬を導き、犬がセーターを着ているということです。彼らは強く結びついています。

ある日、人は姿を消し、犬とセーターだけを残しました。このとき、人と犬のロープのつながりが失われるため、人をGCルーツと考えてください。

その後、犬はリサイクルされる可能性があります、つまり、警察に捕まり、野良犬の搭乗施設に送られます

犬と人との強いつながりを前提とすると、犬は野良犬とはみなされません。

これらのオブジェクトはGCルートとして使用できます

  • 仮想マシンスタック内の参照オブジェクト(スタックフレーム内のローカル変数領域。ローカル変数テーブルとも呼ばれます)
  • メソッド領域のクラスの静的プロパティによって参照されるオブジェクト
  • メソッド領域の定数によって参照されるオブジェクト
  • ネイティブメソッドスタック内のJNI(ネイティブメソッド)の参照オブジェクト

コードの説明


/**
 * 在Java中,可以作为GC Roots的对象有:
 * - 虚拟机栈(栈帧中的局部变量区,也叫做局部变量表)中的引用对象
 * - 方法区中的类静态属性引用的对象
 * - 方法区中常量引用的对象
 * - 本地方法栈中的JNI(Native方法)的引用对象
 */
public class GCRootDemo {
    
    


    // 方法区中的类静态属性引用的对象
    // private static GCRootDemo2 t2;

    // 方法区中的常量引用,GC Roots 也会以这个为起点,进行遍历
    // private static final GCRootDemo3 t3 = new GCRootDemo3(8);

    public static void m1() {
    
    
        // 第一种,虚拟机栈中的引用对象
        GCRootDemo t1 = new GCRootDemo();
        System.gc();
        System.out.println("第一次GC完成");
    }
    public static void main(String[] args) {
    
    
        m1();
    }
}

おすすめ

転載: blog.csdn.net/weixin_43314519/article/details/110309027