【深入學習JVM 03】判斷一個物件是否可回收

Coder_Ring發表於2018-08-27

我們知道,虛擬機器判斷一個物件是否“已死”,是判斷物件是否還有引用指向它。而虛擬機器又是如何判斷是否有引用指向物件呢?

目前,判斷物件是否存活的演算法有兩種:

  • 引用計數演算法
  • 可達性分析演算法

一、引用計數演算法

每個物件都有一個計數器,當這個物件被一個變數引用或者被另一個物件引用時,計數器值就加一,當引用失效時,計數器值就減1,當計數器為0時,則物件不可能再被使用,需要被回收。

二、可達性分析演算法

通過一系列稱為“GC Roots”的物件作為起始點,向下搜尋 走過的路徑稱為“引用鏈”,當一個物件到GC Roots 沒有任何引用鏈,即從GC roots 到這個物件不可達, 則證明物件不可用

可達性分析.png

2.1 可以作為GC Roots的有哪些物件

  1. 虛擬機器棧區域性變數表中引用的物件
  2. 方法區中靜態變數引用的物件
  3. 方法區中常量引用的物件
  4. 本地方法棧中Native方法引用的物件

三、兩種方式對比

  • 引用計數法雖然實現簡單,效率高,但是容易出現迴圈引用。
  • 可達性分析演算法不存在迴圈引用問題,因此是主流的判別方法。

迴圈引用例子:

public class ReferenceCounting {
  public Object data = null;

  public static void test()  {
            ReferenceCounting objA = new ReferenceCounting();
            ReferenceCounting objB = new ReferenceCounting();
            
            objA.data = objB;
            objB.data = objA;
            
            objA = null;
            objB = null;
  }
}
複製程式碼

例子中objA和objB起初所指向的兩個物件已經沒有引用指向它們,但是因為成員變數都引用著對方,所以引用計數不為0,垃圾回收器無法回收。

相關文章