1. 程式人生 > >GC 可達性分析演算法

GC 可達性分析演算法

在主流的商用程式語言的主要實現中,都是稱通過可達性分析(Reachability Analysis)來判定物件是否存活的,這個演算法的基本思路就是通過一系列的稱為“GC Roots“的物件作為起始點,從這些節點開始向下搜尋,搜尋所走過的路程成為引用鏈(Reference Chain),當一個物件到 GC Roots 沒有任何引用鏈相連時,則證明此物件是不可用的。

在Java語言中,可作為 GC Roots 的物件包括下面幾種:

  • 虛擬機器棧(棧幀中的區域性變量表)中引用的物件。(即Java方法中區域性變數引用的物件)
  • 方法區中類靜態屬性引用的物件。(即類的靜態變數引用的物件)
  • 方法區中常量引用的物件。(即類的常量引用的物件)
  • 本地方法棧中 JNI 引用的物件。(即 Native 方法中區域性變數引用的物件)

 

虛擬機器棧:

虛擬機器棧的生命週期與執行緒相同,是執行緒私有的。虛擬機器棧描述的是Java方法執行的記憶體模型:每個方法在執行的同時都會建立一個棧幀(Stack Frame)用於儲存區域性變量表、運算元棧、動態連結、方法出口等資訊,每一個方法從呼叫到執行完畢的過程,就對應著一個棧幀在虛擬機器棧中從入棧到出棧的過程。

 

方法區:

方法區是各個執行緒共享的記憶體區域,它用於儲存已被虛擬機器載入的類資訊、常量、靜態變數、即時編譯器編譯後的程式碼等資料。

 

本地方法棧:

本地方法棧與虛擬機器棧所發揮的作用是相似的,他們之間的區別在於虛擬機器棧為虛擬機器執行 Java 方法服務,而本地方法棧則為虛擬機器使用到的 Native 方法服務(說白了,就是在虛擬機器執行 Native 方法時,用來儲存 Native 方法內的區域性變數等資訊)。

 

 

 


有一個疑問:為什麼Java類的普通變數不能作為 GC Roots 的物件?

在對虛擬機器整體有一個大致瞭解之後,這個問題有了答案:所有通過 new 關鍵字建立的物件全部儲存到 Java堆,而對物件的引用幾乎全部位於虛擬機器棧中,這樣就能通過虛擬機器棧的區域性變量表找到該物件,若該物件的普通成員變數又引用了另外一個物件,這仍然是一條完整的 GC Roots 引用鏈。