在垃圾收集器以前,首先須要判斷哪些對象存活,哪些對象已死(對象死亡的概念表明着,不管經過任何途徑都沒法訪問該對象,沒法被引用鏈可達)算法
在Java中對於對於引用的概念有四種,分別是強引用、軟引用、弱引用、虛引用。緩存
引用計數算法基於一個不變式:當且僅持有某一對象的客戶端集合不爲空時,才能判斷對象存活。在引用算法中,對象要與一個引用計數器相連,這個引用計數器通常在對象的頭部槽中,當該對象被引用時,計數器加一,當引用失效時,計數器減一,當該對象的引用計數器爲空或零時,這時即可將對象回收。多線程
優勢:
1. 引用計數算法的內存管理開銷分攤在程序運行過程當中;
2. 某一對象成爲垃圾即可以當即回收;
3. 能夠持續操做即將滿的內存,不須要預留空間;
4. 當應用程序肯定某一對象並不是共享對象的時候,能夠直接進行破壞性操做,無需建立副本;
5. 引用計數算法無需運行時系統的支持,特別無需肯定程序的根;
缺點:
1. 引用計數給賦值器帶來了額外的時間開銷;
2. 爲避免多線程競爭可能致使對象釋放過早;
3. 在簡單的引用計數當中,哪怕最簡單的讀操做也須要引起一次內存寫請求,這裏的內存寫請求會「污染」高速緩存,同時引發額外的內存衝突;
4. 引用計數算法沒法回收環狀引用結構;
5. 在某些極端狀況下,對象的引用計數器所佔有的空間開銷很是大;
在高級的引用計數算法中能夠解決部分問題,可是同時帶來STW(Stop The World),這樣就喪失了引用計數算法的優點線程
從判斷對象是否死亡的角度出發,垃圾收集算法能夠分爲「引用計數式垃圾收集」和「追蹤式垃圾收集」,而「追蹤式垃圾收集」中有標記-清除(Mark-Sweep)、標記-複製(Mark-Copy)、標記-整理(Mark-Compact),這三種垃圾收集算法雖然處理方式各不相同,可是處理的第一階段倒是同樣,追蹤(trace)階段,此階段正是使用的可達性分析算法進行遍歷和標記(Mark)。3d
從根集合(Root Set)裏面的每個GC Roots的引用關係遍歷GC堆的對象圖,遍歷的路徑稱爲「引用鏈」,若是GC堆裏面某個對象到Root Set沒有引用鏈,就稱爲該對象不可達,對象已經死亡。相似以下圖:cdn
在Java體系裏面,固定能夠做爲GC Roots的對象有以下幾種:對象
優勢:
1. 能夠解決環狀引用;
2. 佔用對象空間少,標記過程只須要在對象頭設置標記位;
缺點:
1. STW(Stop The World),這是一個很嚴重的問題,目前來講,全部的追蹤過程必需要STW;blog
在JVM中判斷一個對象是否存活,依舊要經歷下面幾個過程:生命週期
本文參考《深刻理解Java虛擬機》和《The Garbage Collection Handbook》這兩本書隊列