判斷對象是否已死分析總結——JVM系列(三)

寫在前面:2020年面試必備的Java後端進階面試題總結了一份複習指南在Github上,內容詳細,圖文並茂,有須要學習的朋友能夠Star一下!
GitHub地址:https://github.com/abel-max/Java-Study-Note/tree/masterjava

判斷對象是否已死

判斷對象是否已死就是找出哪些對象是已經死掉的,之後不會再用到的,就像地上有廢紙、飲料瓶和百元大鈔,掃地前要先判斷出地上廢紙和飲料瓶是垃圾,百元大鈔不是垃圾。判斷對象是否已死有引用計數算法和可達性分析算法。git

1.引用計數算法github

給每個對象添加一個引用計數器,每當有一個地方引用它時,計數器值加 1;每當有一個地方再也不引用它時,計數器值減 1,這樣只要計數器的值不爲 0,就說明還有地方引用它,它就不是無用的對象。以下圖,對象 2 有 1 個引用,它的引用計數器值爲 1,對象 1有兩個地方引用,它的引用計數器值爲 2 。面試

image

這種方法看起來很是簡單,但目前許多主流的虛擬機都沒有選用這種算法來管理內存,緣由就是當某些對象之間互相引用時,沒法判斷出這些對象是否已死,以下圖,對象 1 和對象 2 都沒有被堆外的變量引用,而是被對方互相引用,這時他們雖然沒有用處了,可是引用計數器的值仍然是 1,沒法判斷他們是死對象,垃圾回收器也就沒法回收。算法

image

2.可達性分析算法後端

瞭解可達性分析算法以前先了解一個概念——GC Roots,垃圾收集的起點,能夠做爲 GC Roots 的有虛擬機棧中本地變量表中引用的對象、方法區中靜態屬性引用的對象、方法區中常量引用的對象、本地方法棧中 JNI(Native 方法)引用的對象。ide

當一個對象到 GC Roots 沒有任何引用鏈相連(GC Roots 到這個對象不可達)時,就說明此對象是不可用的,是死對象。學習

以下圖:object一、object二、object三、object4 和 GC Roots 之間有可達路徑,這些對象不會被回收,但 object五、object六、object7 到 GC Roots 之間沒有可達路徑,這些對象就被判了死刑。對象

image

上面被判了死刑的對象(object五、object六、object7)並非必死無疑,還有挽救的餘地。進行可達性分析後對象和 GC Roots 之間沒有引用鏈相連時,對象將會被進行一次標記,接着會判斷若是對象沒有覆蓋 Object的finalize() 方法或者 finalize() 方法已經被虛擬機調用過,那麼它們就會被行刑(清除);若是對象覆蓋了 finalize() 方法且尚未被調用,則會執行 finalize() 方法中的內容,因此在 finalize() 方法中若是從新與 GC Roots 引用鏈上的對象關聯就能夠拯救本身,可是通常不建議這麼作,周志明老師也建議你們徹底能夠忘掉這個方法~內存

3.方法區回收

上面說的都是對堆內存中對象的判斷,方法區中主要回收的是廢棄的常量和無用的類。

判斷常量是否廢棄能夠判斷是否有地方引用這個常量,若是沒有引用則爲廢棄的常量。

判斷類是否廢棄須要同時知足以下條件:

  • 該類全部的實例已經被回收(堆中不存在任何該類的實例)。

  • 加載該類的 ClassLoader 已經被回收。

  • 該類對應的 java.lang.Class 對象在任何地方沒有被引用(沒法經過反射訪問該類的方法)。
相關文章
相關標籤/搜索