淺談常用四種垃圾回收算法總結——JVM系列(四)

常用四種垃圾回收算法

常用的垃圾回收算法有四種:標記-清除算法、複製算法、標記-整理算法、分代收集算法。

1.標記-清除算法

分爲標記和清除兩個階段,首先標記出所有需要回收的對象,標記完成後統一回收所有被標記的對象,如下圖。

缺點:標記和清除兩個過程效率都不高;標記清除之後會產生大量不連續的內存碎片。

image

2.複製算法

把內存分爲大小相等的兩塊,每次存儲只用其中一塊,當這一塊用完了,就把存活的對象全部複製到另一塊上,同時把使用過的這塊內存空間全部清理掉,往復循環,如下圖。

缺點:實際可使用的內存空間縮小爲原來的一半,比較適合。

image

3.標記-整理算法

先對可用的對象進行標記,然後所有被標記的對象向一段移動,最後清除可用對象邊界以外的內存,如下圖。

image

4.分代收集算法

把堆內存分爲新生代和老年代,新生代又分爲 Eden 區、From Survivor 和 To Survivor。一般新生代中的對象基本上都是朝生夕滅的,每次只有少量對象存活,因此採用複製算法,只需要複製那些少量存活的對象就可以完成垃圾收集;老年代中的對象存活率較高,就採用標記-清除和標記-整理算法來進行回收。

image

在這些區域的垃圾回收大概有如下幾種情況:

大多數情況下,新的對象都分配在Eden區,當 Eden 區沒有空間進行分配時,將進行一次 Minor GC,清理 Eden 區中的無用對象。清理後,Eden 和 From Survivor 中的存活對象如果小於To Survivor 的可用空間則進入To Survivor,否則直接進入老年代);Eden 和 From Survivor 中還存活且能夠進入 To Survivor 的對象年齡增加 1 歲(虛擬機爲每個對象定義了一個年齡計數器,每執行一次 Minor GC 年齡加 1),當存活對象的年齡到達一定程度(默認 15 歲)後進入老年代,可以通過 -XX:MaxTenuringThreshold 來設置年齡的值。

當進行了 Minor GC 後,Eden 還不足以爲新對象分配空間(那這個新對象肯定很大),新對象直接進入老年代。

佔 To Survivor 空間一半以上且年齡相等的對象,大於等於該年齡的對象直接進入老年代,比如 Survivor 空間是 10M,有幾個年齡爲 4 的對象佔用總空間已經超過 5M,則年齡大於等於 4 的對象都直接進入老年代,不需要等到 MaxTenuringThreshold 指定的歲數。

在進行 Minor GC 之前,會判斷老年代最大連續可用空間是否大於新生代所有對象總空間,如果大於,說明 Minor GC 是安全的,否則會判斷是否允許擔保失敗,如果允許,判斷老年代最大連續可用空間是否大於歷次晉升到老年代的對象的平均大小,如果大於,則執行 Minor GC,否則執行 Full GC。

當在 java 代碼裏直接調用 System.gc() 時,會建議 JVM 進行 Full GC,但一般情況下都會觸發 Full GC,一般不建議使用,儘量讓虛擬機自己管理 GC 的策略。

永久代(方法區)中用於存放類信息,jdk1.6 及之前的版本永久代中還存儲常量、靜態變量等,當永久代的空間不足時,也會觸發 Full GC,如果經過 Full GC 還無法滿足永久代存放新數據的需求,就會拋出永久代的內存溢出異常。

大對象(需要大量連續內存的對象)例如很長的數組,會直接進入老年代,如果老年代沒有足夠的連續大空間來存放,則會進行 Full GC。

讀者分享

針對於上面的文章我總結出了互聯網公司java程序員面試涉及到的絕大部分面試題及答案做成了文檔和架構視頻資料免費分享給大家(包括Dubbo、Redis、Netty、zookeeper、Spring cloud、分佈式、高併發等架構技術資料),希望能幫助到您面試前的複習且找到一個好的工作,也節省大家。

資料免費領取方式:加q羣:328993819 【點擊立即加入】 找管理小姐姐免費獲取!

更多架構專題及視頻資料展示如下:


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