最新java虛擬機面試題分享:G1 GC的回收機制

簡單來說,G1 GC的收集分為4個階段:年輕代GC,並發標記周期,混合回收和full GC。

年輕代GC

G1 GC的年輕代回收基本沿襲瞭之前的設計,通過復制算法和一個Eden區、兩個Survivor區實現。但區別在於,大對象的分配是可以直接到大對象區間的(詳見上文)。此外,在每一次年輕代回收暫停期間,G1 GC會計算當前年輕代大小需要擴展或者壓縮的總量,例如增加或者刪除空閑區間、統計Rset大小、當前最大可用年輕代、當前最小可用年輕代、設置停頓目標等。我們可以認為這個過程在回收停頓結束後是一個重新調整年輕代的過程。可以通過-XX:+PrintGCDetails選項的運行來查看具體數據。

並發標記

G1 GC設定瞭一個閾值,默認值是堆內存的45%。這個閾值可以通過選項IHOP設定,IHOP即-XX:InitiatingHeapOccupanyPercent。當超過閾值時,GC會自動進入並行標記循環。並行標記循環的最終目標是在整個Java堆達到滿載之前完成標記動作,同時為瞭確保Java應用線程可以並行運行,並行標記循環的內部標記任務被劃分成瞭很多塊任務,這樣可以做到並行執行。

並行標記循環的過程分為五個階段:

1.初始標記階段

把java堆中所有能被根可達的對象標記出來,在此期間應用線程暫停。

2.根區間掃描階段

並發掃描和跟蹤survivor區所有對象引用。

3.並行標記階段

多個線程協同表示存活對象。並發並行執行。

4.重新標記階段

最終完成所有標記工作,短暫stop-the-world。

5.清除階段

將沒有任何存活對象的分區回收,梳理RSet,將沒有引用的分區加入可用隊列。

混合回收

混合回收和年輕代回收暫停的工作方式類似,也是通過拷貝方式完成針對存活對象的壓縮操作。唯一的區別是在混合回收階段,回收集合也會和一些被認定為是可以做垃圾回收的老年代一起合作,即同時對年輕代和老年代區間進行回收。通過配置一些參數,可以為一次混合回收循環設定多次混合回收暫停。一次混合回收循環隻有在標記或者超過IHOP闊值時才會觸發啟動,且必須發生在一次並行標記循環之後。

可配置參數:

-XX:-G1MixedGCCountTarget

DK8u45默認值為8, 意味著混合GC數目目標為8個,即標記循環完成之後開始的混合回收數目從物理上被限制在瞭8個。每一次混合回收暫停的最小老年代區間數目的計算公式為:

每一次混合回收暫停的最小老年代區間數目=混合收集循環確認的候選老年代區間總數/G1MixedGCCountTarget。

-XX:G1HeapWastePercent

JDK8U45默認值為整個堆空間的5%, 這個選項對於控制一次混合回收循環回收的老年代區間數量有很大的影響作用。對於每一次混合回收暫停, G1 GC基於死亡對象空間確認所有可以回收的堆內存,即事先已經統計好瞭每個區間還有多少存活對象,通過拷貝的方式移出區間,再把這些區間加入空閑區間。當G1 GC達到堆內存空閑閾值百分比限制時,G1 GC停止初始化混合回收暫停。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。