判定對象是否存活算法
1、引用計數算法
給對象中添加一個引用計數器,每當一個地方引用它時,計數器值就+1;當引用失效時,計數器值就-1;任何時刻計數器爲0的對象就是不可能再被使用的。
優點:實現簡單,判定效率高
缺點:很難解決對象相互循環引用問題
對於JVM,並不是使用此算法,使用的是第二種算法:可達性分析算法。
如下示例看GC日誌發現,objA和objB相互引用,顯示置爲null之後,進行GC時不會因爲相互引用而不回收objA和objB,所以證明JVM並不是使用的引用計數算法。
public class ReferenceCountingGc{
public Object instance=null;
private static final int _1MB=1024*1024;
private byte[] bigSize= new byte[2*_1MB];
public static void testGC(){
ReferenceCountingGC objA=new ReferenceCountingGC();
ReferenceCountingGC objB=new ReferenceCountingGC();
objA.instance=objB;
objB.instance=objA;
objA=null;
objB=null;
System.gc();
}
}
2、可達性分析算法
在主流商用程序語言(Java、C#)的主流實現中,都是通過可達性分析來判定對象是否存活的。
基本思路是通過一系列稱爲"GC Roots"的對象作爲起始點,從節點開始向下搜索,搜索所走過的路徑成爲引用鏈,當一個對象到GC Roots沒有任何引用鏈相連時,則證明此對象時不可用的。
在java語言中,可作爲GC Roots的對象包括下面幾種:
- 虛擬機棧(棧幀中的本地變量表)中引用的對象。
- 方法區中類靜態屬性引用的對象。
- 方法區中常量引用的對象。
- 本地方法棧中JNI(既一般說的Native方法)引用的對象。
JDK引用
- 強引用
- 強引用指類似
Object obj=new Object()
這類的引用,只要強引用還在,垃圾收集器永遠不會回收掉被引用的對象。 - 軟引用
- 軟引用是用來描述一些還有用但並非必需的對象。在系統將要發生內存溢出異常之前,將會把軟引用對象列進回收範圍進行二次回收。如果這次回收之後還是沒有足夠內存,纔會拋出內存溢出異常。在JDK1.2之後,提供了SoftReference類來實現軟引用。
- 弱引用
- 弱引用關聯的對象只能存活到下一次GC發生之前。當GC開始時,無論內存是否足夠,都會回收弱引用關聯的對象。在JDK1.2之後,提供了WeakReference類實現。
- 虛引用
- 一個對象是否有虛引用的存在,完全不會對其生存時間構成影響,也無法通過虛引用來取得一個對象實例。虛引用的唯一目的是在這個對象被GC時收到一個系統通知。在JDK1.2之後,提供了PhantomReference類實現。