JVM 記憶體管理-----JVM如何判斷物件已死
阿新 • • 發佈:2019-02-14
分享前丟擲幾個問題?
▪ 如何判斷一個物件是否存活著?
▪為什麼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方法)引用的物件。