【Java面試】GC如何判斷對象是否死亡

引用計數算法(不採用)

給對象中添加一個引用計數器,每當有一個地方引用它,計數器就加 1;當引用失效,計數器就減 1;任何時候計數器爲 0 的對象就是不可能再被使用的。

此方法是最簡單的實現方法,但是無法解決對象相互循環引用的問題。
下面是一段僞代碼。


Obj a = new Obj();// a = 1
Obj b = new Obj();// b = 1

a.instance = b;//b = 2
b.instance = a;//a = 2

a = null;// (a去掉Obj引用 - 1)a = 1
b = null;// (b去掉Obj引用 - 1)b = 1

// 垃圾回收
System.gc();

[GC (System.gc()) [PSYoungGen: 5248K->863K(76288K)] 5248K->871K(251392K), 0.0014251 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (System.gc()) [PSYoungGen: 863K->0K(76288K)] [ParOldGen: 8K->713K(175104K)] 871K->713K(251392K), [Metaspace: 3325K->3325K(1056768K)], 0.0081160 secs] [Times: user=0.11 sys=0.00, real=0.01 secs] 

我們知道,引用計數器的方式是沒辦法解決循環引用的情況,但是從GC日誌中我們可以看出,還是被正確回收了,也就表明它並不是使用該方式。

這就引申出了一個新的知識,就是循環引用,我們來了解一下循環引用是如何出現的,和造成無法解決循環引用的原因。

循環引用1
我們把左下角這個對象當成A對象,右下角對象當成B對象。
這個圖中,我們可以看到A對象被Java棧中的Obj1-reference引用,被Java堆中的B對象引用;B對象被Obj2-reference引用,被A對象引用。

那麼我們摘除了A對象中Obj1-reference的引用,B對象Obj2-reference的引用,我們發現只剩下了。

循環引用2
我們把承接對象A的引用已經斷開了,我們就無法再操作裏面的對象內容了,我們無法把對象A中的ref對象置爲null,如果使用了該算法的話,那就會導致了這兩個在堆中的對象一直無法被垃圾回收清除了,因爲計數器中的值永遠不會降到0,除非我們手動去幹預或者後續再去處理這種情況。
循環引用3
更加硬核一點的理解方法如圖,當我們把直接p的指向去掉了,那麼我們就無法再使用p這個指針對被原有指針p引用的對象進行操作了,所以這部分就只能通過其他手段去釋放內存空間了。Java中我們沒有辦法手動去釋放這些空間,當然Java也沒有使用該算法作爲垃圾回收標記的算法,他使用的是可達性分析算法。


可達性分析算法可達性分析算法

這個算法的基本思想就是通過一系列的稱爲 “GC Roots” 的對象作爲起點,從這些節點開始向下搜索,節點所走過的路徑稱爲引用鏈,當一個對象到 GC Roots 沒有任何引用鏈相連的話,則證明此對象是不可用的。

可作爲GC Roots的對象

  • 虛擬機棧中引用的對象
  • 方法區中類靜態屬性引用的對象
  • 方法區中常量引用的對象
  • 本地方法棧中JNI引用的對象

生存還是死亡

判斷一個對象的生存還是死亡,在Java中,主要經過兩次標記的過程,第一次經過可達性分析算法,判斷是否GC Roots可達,如果不可達,則標記該對象“死緩”;第二次則判斷是否重寫finalize方法,如果重寫該方法則把該對象加入F-Queue隊列中,稍後由JVM虛擬中優先級比較低的線程Finalizer中執行該方法,並且該方法不等待執行的結果,因爲這部分被重寫的代碼最壞情況可能導致隊列的阻塞,GC在稍後就會對F-Queue中的對象進行二次標記,如果該對象沒有在這個時間內被重新與GC Roots的對象產生關聯,那麼就會被標記爲垃圾對象,宣判死亡。


總結

  1. 可達性分析算法標記GC Roots不可達對象;
  2. 判斷是否重寫finalize方法,沒重寫則宣判死亡;
  3. 如果重寫,則加入F-Quene隊列在finalizer線程中執行;
  4. 如果對象沒有重新產生關聯(再次可達性分析算法),則標記垃圾對象;
  5. GC處理垃圾對象。

參考資料

JVM垃圾回收對象判定標準之可達性分析算法(根搜索法)
JVM之GCRoots概述
引用計數法的循環引用問題
垃圾回收算法之引用計數算法
垃圾回收機制中,引用計數法是如何維護所有對象引用的?
《深入理解Java虛擬機:JVM高級特性與最佳實踐》

文章中出現的任何錯誤歡迎指正!共同進步!

最後做個小小廣告,有對WEB開發和網絡安全感興趣的,可以加羣一起學習和交流!

交流羣
QQ:425343603

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章