GC對象回收(垃圾回收)

一、什麼樣的對象該回收:沒有任何引用的對象。

二、怎麼判斷對象是否不具有引用:有兩種方法,一種是引用計數算法,另外一種是可達性分析算法。

引用計數算法:對象中會有一個引用計數器,每有一個對該對象的引用就會在計數值上+1,當計數值爲0的時候,該對象便不再有引用。

可達性分析算法(Java主流算法):會設置一個”GC Roots“對象,該對象可以是各種引用的對象,當一個對象沒有到”GC Roots“對象的任何引用鏈時,那麼這個對象就是可回收的;具體如下圖所示(該圖來自《深入理解Java虛擬機》):

三、爲了使gc回收更加靈活,Java爲對象分成了如下四種不同的狀態:

強引用——普遍的引用類型,只要強引用還在就不會被回收(如:Object obj = new Obje(););

軟引用——可有可無的對象,在內存溢出之前會被回收;

弱引用——gc運行時時就會回收的對象;

虛引用——無法通過該引用獲取對象的實例,被回收時會收到一個系統通知。

四、垃圾回收算法:

標記-清除算法:顧名思義,將要回收的對象標記然後清除標記對象,其問題就是效率低下,並且會產生大量的內存碎片(內存碎片較多時可能會導致較大的對象申請不到內存空間);該算法是CMS收集器(當時所謂的最快收集器)使用的算法,分爲四步:初步標記、併發標記、重新標記、併發清除;它之所以比較快是因爲實際上會停止程序運行的只有初步標記與重新標記兩個步驟,而比較耗時的併發標記與併發清除則是與程序同時運行的(垃圾回收時爲了確保對象狀態的確定性會暫時停止所有線程,而重新標記就是爲了糾正併發標記時程序運行導致的對象狀態的改變);具體原理如下圖所示(該圖來自《深入理解Java虛擬機》):

複製算法:該算法會將內存分成兩個區域,一個區域是空白的,另一個區域纔是真正被使用的,當gc的時候,被使用區域會將存活的對象都cp到空白區域中,這樣就可以直接將使用區域的對象全部清除從而提高效率(但如果存活率較高,那麼效率就會相應變低),並且這樣清除會讓對象存放比較整齊,只要通過移動指針便可添加新的對象;但其缺點也是比較明顯的,會浪費一部分內存作爲gc時存放存活對象的不可以用的空白區域;具體原理如下圖所示(該圖來自《深入理解Java虛擬機》,感覺這張圖有點偷懶了):

標記-整理算法:簡單的說就是將存活的對象向一端移動,然後以此爲界限將其它的內存全部清空;具體原理如下圖所示(該圖來自《深入理解Java虛擬機》):

分代收集算法:在以上三種算法的基礎上誕生的,該算法通過在新生代使用複製算法(由於新生代的對象大都朝生夕死,所以對象存活率較低),在老年代使用標記-清除或標記-整理的算法。

除此之外,通過以上的垃圾回收算法誕生了各種各樣的垃圾收集器,前面提到的CMS收集器就是其中一種,不同的虛擬機所使用的垃圾收集器也各不相同;而Java自7開始就使用G1替換掉了CMS,而G1在很多方面與CMS有很多的相同之處,但它比CMS各方面都更加完善,使用的卻是”標記-整理“的算法,主要分爲以下幾個步驟:初始標記、併發標記、最終標記、篩選回收。

發佈了49 篇原創文章 · 獲贊 11 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章