JVM判断对象是否存活

堆中几乎存放着所有的对象实例,垃圾收集器在对堆回收之前,第一件事情就是要确定这些对象哪些还“存活”,那些对象已经“死去”(即不可能被任何途径使用的对象)

一、引用计数算法(Reference Counting)

给对象中添加一个引用计数器,每当又一个地方引用它时,计数器值加1;当引用失效时,计数器减1;任何时刻计数器都为0的对象就是不可能在被使用的.但是Java语言中没有选用引用计数法来管理内存,其中最主要的原因是它很难解决对象之间相互循环依赖的问题.

例如: 在testGC中,对象objA和对象objB都有字段instance,赋值objA.instance=objB.instance及objB.instance=objA.instance,除此之外这两个对象再无其他任何引用,实际上这两个对象都已经不能再被访问,但是他们因为他们互相引用着对方,他们的引用计数都不为0,于是引用计数算法无法通知GC收集器回收它们. 打印GC详细信息: -XX:+PrintGCDetails

public class ReferenceCountingGC {

    public Object instance = null;

    public static void main(String[] args) {
        ReferenceCountingGC objA = new ReferenceCountingGC();
        ReferenceCountingGC objB = new ReferenceCountingGC();
        objA.instance = objB;
        objB.instance = objA;


        objA = null;
        objB = null;

        //假设在这行发生了gc,objA和objB是否被回收
        System.gc();
    }
}
复制代码

GC日志为:

[GC (System.gc()) [PSYoungGen: 334480K->4736K(334848K)] 597914K->270331K(1017536K), 0.0019879 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 
[Full GC (System.gc()) [PSYoungGen: 2408K->0K(298688K)] [ParOldGen: 0K->3363K(682688K)] 3408K->3363K(981376K), [Metaspace: 3162K->3162K(1056768K)], 0.0050515 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 
Heap
 PSYoungGen      total 153088K, used 3947K [0x0000000715580000, 0x0000000720000000, 0x00000007c0000000)
  eden space 131584K, 3% used [0x0000000715580000,0x000000071595afc0,0x000000071d600000)
  from space 21504K, 0% used [0x000000071d600000,0x000000071d600000,0x000000071eb00000)
  to   space 21504K, 0% used [0x000000071eb00000,0x000000071eb00000,0x0000000720000000)
 ParOldGen       total 349696K, used 872K [0x00000005c0000000, 0x00000005d5580000, 0x0000000715580000)
  object space 349696K, 0% used [0x00000005c0000000,0x00000005c00da3b8,0x00000005d5580000)
 Metaspace       used 3169K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 346K, capacity 388K, committed 512K, reserved 1048576K
复制代码

GC日志分析:

GC (minor )日志:

Full GC 日志:

后半段分析

对照上面的图,GC日志中的PSYoungGen(PS是指Parallel Scavenge)为Eden+FromSpace,而整个YoungGeneration为Eden+FromSpace+ToSpace。

我们设置的新生代大小为10240K,这包括9216K大小的PSYoungGen和1024K大小的ToSpace。其中,PSYoungGen中的Eden:FromSpace为8:1,

这包括8192K的Eden和1024K的FromSpace。

详细日志输出:

参数设置为:

-XX:+ PrintGCDetails -XX:-UseAdaptiveSizePolicy -XX:SurvivorRatio = 8 -XX:NewSizeパラメータ= 10M -XX:MaxNewSize = 10M

パラメータの説明:

-XX:+ PrintGCDetailsは、ログを有効にします

-XX:あなたはSurvivorRatioを働かせることができるように、動的な調整を無効-UseAdaptiveSizePolicy

-XX:SurvivorRatio = 8エデンを配置:Survivior = 8

-XX:NewSizeパラメータ= 10M -XX:MaxNewSize = 10M全く新しい世代の10Mのサイズを設定します

デフォルトのガベージコレクタは次のとおりです。パラレル清掃を

実行ログの結果では、我々は(2M、実際には、OBJAとobjB程度)2408Kから歳、GCログ「は2408K-> 0K」が含まれて見ることができる2つのオブジェクトが相互に参照するため、仮想マシンがないことを意味し、512Kとなり作成したオブジェクトを入力するための新しい世代に割り当てられているとき、彼らは、オブジェクトが古い時代に見ることができます。それはまた、生き残ったオブジェクトかどうかを判断するために仮想マシンが参照カウント法によって組み込まれていないことを証明し、回復していないが、我々はすべて知っていますジョブの新しいOBJAのニーズに古いが、ここではOBJAとobjBは、古い時代に入った。Javaヒープは古いルールといくつかの年に始まり、ヒープの小さなオブジェクトに動的に成長するためである、ときsurviorスペース同世代のオブジェクトの大きさと半分以上survior空間のとき、オブジェクトは、古い時代に直接移動します。

第二に、到達可能性解析アルゴリズム(GCのルーツ分析):この判決で主流

アルゴリズムのこの基本的な考え方は、出発点として「GCルート」と呼ばれるオブジェクトのシリーズがある場合、これらのノードは、オブジェクトがGCルーツいかなる参照チェーンに接続されていないときに呼び出される参照のチェーンを検索する経路ダウン先頭から検索します達した根をGCにお互いを分析するが、それらはないが、そのオブジェクトがこれを証明するために使用することができない、グラフオブジェクトobject5は、object6、object7、それらがリサイクル可能オブジェクトであると判断されます

GCのルーツオブジェクトが含まれているJava言語では、次のとおりです。

  • 図1に示すように、仮想マシンのスタック(テーブルのスタックフレーム内のローカル変数)オブジェクト参照
  • 図2に示すように、メソッド領域静的プロパティクラスオブジェクト参照
  • 3.オブジェクト参照の定常領域の方法
  • JNI参照オブジェクトの4、ネイティブメソッドスタック

三、ファイナライズ()メソッドは、最終的にオブジェクトが生きているかどうかを決定します

解析アルゴリズムの目的は、中まで到達不能としても、それは「Feisibuke」ではない、と彼らは、「保護観察」段階に一時的にしているこの時間は、本当にラベリングプロセスを通過するには、少なくとも二回、オブジェクトの死を宣言する。前提がマークされています到達可能性分析の間のオブジェクトが互いに結合GC根に関連しない参照が見つからない場合。

1、最初の時間と最初のスクリーニングをマーク

スクリーニング条件は、仮想マシン上で起動されたオブジェクトはファイナライズ()メソッドをカバーしています。またはメソッドを確定していない場合。このオブジェクトは、ファイナライズ()メソッドを実行する必要があるかどうかで、仮想マシンは、これらの2つの場合は、「実行する必要はない」と考えられていますオブジェクトが回収され、

2、第2マーク

オブジェクトがファイナライズ()メソッドを実行するために必要であると判定された場合、オブジェクトは、F-キューと呼ばれるキューに配置され、それ以降自動的に低優先度のスレッドのファイナライザを確立するために仮想マシンによって行っそれを実行します。ここでは、いわゆる「実行」は、このメソッドをトリガーする仮想機会であるのですが、遅い実装のfinalize()メソッド、または死亡の発生におけるオブジェクトならば、それは、ランの終わりのためにその理由をお待ちしております約束していませんサイクル、おそらく永久に待機中のF-キューキュー他のオブジェクトになり、さらには全体のメモリ回収システムが.finalize()メソッドは、オブジェクトの死の運命を脱出する最後のチャンスであるとクラッシュする原因となります、後のGCは中F-キューオブジェクトになります第2の小マーク、オブジェクトが自分のレスキューファイナライズに成功する場合()---限り再確立は、いずれかの参考文献の鎖上の任意のオブジェクトに関連付けられているように、例えば、それ自体(このキーワード)に割り当てられました変数やオブジェクトのクラスメンバ変数、それはコレクションに削除されます「回復することを、」第二のタイムマーク;オブジェクトは、この時間をエスケープしていない場合、それは本当に基本的にリサイクルしていることです A.

このフローチャートは以下のようです:

public class FinalizeEscapeGC {
    public static FinalizeEscapeGC SAVE_HOOK = null;

    public void isAlive(){
        System.out.println("yes,i am still alive:");
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("finalize method executed!");
        FinalizeEscapeGC.SAVE_HOOK = this;
    }

    public static void main(String[] args) throws InterruptedException {
        SAVE_HOOK = new FinalizeEscapeGC();
        //对象第一次成功解救自己
        SAVE_HOOK = null;
        System.gc();
        //因为finalize方法优先级很低,所以暂停0.5秒以等待它
        Thread.sleep(500);
        if (SAVE_HOOK != null){
            SAVE_HOOK.isAlive();
        }else {
            System.out.println("no,i am dead:(");
        }

        //下面这段代码与上面的完全的相同,但是这次自救却失败了
        SAVE_HOOK = null;
        System.gc();
        //因为finalize方法优先级很低,所以暂停0.5秒以等待它
        Thread.sleep(500);
        if (SAVE_HOOK != null){
            SAVE_HOOK.isAlive();
        }else {
            System.out.println("no,i am dead:)");
        }
    }
}
复制代码

結果:

finalize method executed!
yes,i am still alive:
no,i am dead:)
复制代码

操作の結果から明らかなように、SAVE_HOOKオブジェクトをファイナライズ()メソッドは、GCのコレクタはトリガー、および正常に収集される前にエスケープされない。コードは、2つの同一のコードフラグメントを有し、その結果は、成功したエスケープの実装でありますオブジェクトがファイナライズの回復に直面している場合は任意のオブジェクトをファイナライズ()メソッドは、唯一の方法は再び実行され、したがって、自助行動コードの第2段落されません)(、システムと自動的に呼び出されますので、障害、これは、より良く、よりタイムリーに行うことができますのtry-最終的またはそれ以外の場合は使用して、すべての作業を行うことができます.finzlizeを()が失敗しました。しかし、あなたは完全にこのメソッドのJava言語の存在を忘れることを示唆しています。

ます。https://juejin.im/post/5d08bc84f265da1b8b2b60daで再現

おすすめ

転載: blog.csdn.net/weixin_34375233/article/details/93166278