1. 程式人生 > >JVM 記憶體管理-----JVM如何判斷物件已死

JVM 記憶體管理-----JVM如何判斷物件已死

分享前丟擲幾個問題?

如何判斷一個物件是否存活著?

為什麼java堆記憶體要分代?

個物件從建立到被回收經歷了哪些過程,如果是很大的物件呢?

哪些情況會報outofMemoryError,StackOverFlowError?

Jvm調優的配置引數,你都知道麼?

一、物件已經死了麼?

引用計數法?

▪可達性分析

引用計數法

物件有被引用,則引用計數器加1

通過如下示例判斷jvm是否是使用的是引用計數法?,如下示例是兩個物件互相引用這對方,並且無其他引用,如果是使用引用計數法,那麼將不會被回收,如果不是,則可以被回收

/**
 * @author hezg
 * 測試物件相互引用是否可以被回收
 */
public class ReferenceCountingGC {
    public Object instance = null;
    private static final int _1MB = 1024 * 1024;
    private byte[] bigSize = new byte[2 * _1MB];

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

        objA = null;
        objB = null;

        System.gc();
    }
}

執行結果:

從圖示[PSYoungGen: 8031K->798K(76288K)] 說明兩個物件示例都是有被回收的。顯然jvm不是使用引用計數法回收物件。

可達性分析

jvm使用可達性分析演算法來判斷物件是否存活。

這個演算法是通過一系列稱為"GCRoot"的物件作為起始點,從這些節點開始向下搜尋,搜尋所走過的路徑稱為引用鏈,當一個物件到GC Root是沒有任何引用鏈相連線,則說明此物件是不可用的,如圖:

圖中可以很明顯的知道,物件1-7到GCRoot是可達的,即物件還存活著,物件8-11到GCRoot是不可達的,即物件已死。

那麼什麼樣的物件可以作為GCRoot呢?有如下四種

虛擬機器棧(棧幀中的本地變量表)中引用的物件。

方法區中類靜態屬性引用的物件。

方法區中常量引用的物件。

本地方法棧中JNI(即一般說的Native方法)引用的物件。