首先說爲何要判斷是否存活,當垃圾收集器在對堆進行回收前,第一就是要肯定對象哪些是還在被引用的或者後面還須要被引用的,即存活,哪些是已經「死去」(即不可能再被任何途徑使用)面試
一、引用計數算法
在對象中添加一個引用計數器,每當有一個地方引用它時,計數器值就加1,引用失效時就減1.任什麼時候刻計數器爲0的對象就是不可能再被使用的。這個方法效率挺高,大部分狀況下也是很不錯的算法。redis
可是在JVM中會很難解決對象之間相互循環引用的問題,就若是兩個對象之間相互調用,這時候就會發生相似死鎖的狀況,即這個地方相互調用會使得引用計數法始終認爲有對象在引用當前對象,就一直計數值大於或等於1,也就沒法通知GC收集器回收它們。可是實際的狀況是這兩個對象後面已經再也不調用,因此這個方法雖然簡單高效,但不是咱們的首選。虛擬機也不是經過這個算法來判斷對象是否存活的。算法
二、可達性分析算法
使用一系列的GC Roots的對象(包括:虛擬機棧中引用的對象,方法區中類靜態屬性引用的對象,方法區中常量引用的對象,本地方法棧中JNI引用的對象)做爲起點,從節點開始向下搜索,當沒有被GCRoots連接到的對象就能夠回收,以下圖的對象4和5就判斷爲可回收對象。設計模式
在JDK1.2以後,Java對引用這個概念進行了擴充,也就是對象不單單隻有引用和沒有引用兩個概念,而是擴展到了4個:併發
強引用:相似於「Object obj=new Object()」只要強引用在,垃圾收集器永遠不會回收掉被引用的對象。ide
軟引用:是用來描述一些還有用可是並不是必需的對象,對於軟引用對象,在內存溢出異常以前,會把這些對象列進回收範圍之中進行第二次回收。工具
弱引用,比軟引用更弱一點,被弱引用關聯的對象只能生存到下一次垃圾收集發生以前。當垃圾收集發生時不管內存是否足夠,都會只回收弱引用的對象。spa
虛引用,最弱的引用關係,對象是否有虛引用對其生存時間是沒有影響的。惟一目的就是能在這個對象被收集器回收時收到一個系統通知。翻譯
對象要想真正宣告「死亡」須要至少兩次的標記過程,當對象在可達性分析時候發現沒有被GC Roots鏈到那麼對象就會進行第一次標記而且進行第一次篩選,篩選的條件就是判斷該對象有沒有必要執行finalize()方法,須要執行的話就會把對象放入F-Queue的對列中去執行該對象中的finalize()方法。若是finalize()方法讓對象從新被GC Roots鏈到那麼對象就從新活下來,不然就會進行第二次標記,等待垃圾回收的到來設計
能夠做爲GC Roots 的對象:
-
虛擬機棧中引用的對象;
-
方法區中類靜態屬性引用的對象;
-
方法區中常量引用的對象;
- 本地方法棧中JNI引用的對象;
推薦閱讀:
-
深刻解析HashMap和ConcurrentHashMap源碼以及底層原理
-
設計模式(二):幾種工廠模式詳解
-
進程同步的五種機制以及優缺點(翻譯)
-
redis五種數據類型的實現方式,經常使用命令,應用場景
-
redis和memcahed的共同點,區別以及應用場景
-
詳解TCP的三次握手與四次揮手及面試題(很全面)
-
Arrays 工具類詳解(超詳細)
-
算法必須掌握幾種方法
-
QPS、TPS、併發用戶數、吞吐量
-
設計模式之單例模式
- Collections 工具類詳解(超詳細)