【Java虛擬機器】判斷物件是否存活的演算法
阿新 • • 發佈:2018-12-03
判斷物件是否存活的演算法
判斷物件是否存活的演算法
引用計數演算法
引用計數演算法是這樣的:給物件中新增一個引用計數器,每當一個地方引用時,計數器值就加1;當引用失效時,計數器值就減1;任何時刻計數器為0的物件就是不可能再被使用的。
主流的Java虛擬機器裡面沒有選用引用計數器演算法來管理記憶體,其中最主要的原因就是它很難解決物件之間迴圈引用的問題。
舉個例子:
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();
}
}
objA和objB都有欄位instance,賦值objA.instance = objB以及objB.instance = objA,除此之外,這兩個物件再無任何引用,實際上這兩個物件已經不可能再被訪問,但是它們因為互相引用著對方,導致它們的引用計數都不為0,於是引用技術演算法無法通知GC收集器回收它們。
可達性分析演算法
可達性分析演算法的基本思想就是通過一系列的成為“GC Roots”的物件作為起始點,從這些起始點開始向下搜尋,搜尋所經過的路徑稱為引用鏈,當一個物件到GC Roots沒有任何引用鏈相連(用圖論的話來說,就是從GC Roots到這個物件不可達)時,則證明此物件是不可用的。
舉個例子:
如上圖,物件object5、object6、object7雖然互相有關聯,但是它們到GC Roots是不可達的,所以它們將會被判定為是可回收的物件。
在Java語言中,可作為GC Roots的物件包括下面幾種:
- 虛擬機器棧中引用的物件
- 本地方法棧JNI(即一般說的Native方法)所引用的物件
- 方法區中類靜態屬性引用的物件
- 方法區中常量引用的物件
參考
- 深入理解Java虛擬機器[書籍]