JVM-垃圾回收(3)
阿新 • • 發佈:2022-05-06
垃圾回收器補充——G1(Garbage First)
G1垃圾回收器在2012年JDK 7u4中得到官方支援
而在2017年的JDK9更是將其設定為預設的垃圾回收器
G1的特點很多:
- 同時注重吞吐量(Throughput)和低延遲(Low Latency),預設的暫停目標是200ms
- 適用超大的堆記憶體,會將堆劃分為多個大小相等的區域Region
- 整體採用標記-整理演算法,而兩個區域Region之間採用複製演算法
相關的JVM引數:
-XX:UseG1GC
-XX:G1HeapRegionSize=size
-XX:MaxGCPauseMillis=time
解釋:
- 啟動G1
- 設定區域的大小
- 設定暫停目標
G1的垃圾回收過程
1. G1的堆結構和堆分配
G1的堆結構分為許多固定大小的區域,這些區域被對映到伊甸園、倖存區和老年代的邏輯表示中。
就以上面的圖片為例,綠色的是伊甸區,黃色的是倖存區,藍色的是老年代
值得注意的是,這些區域不需要像之前的的垃圾收集器那樣相連。
此外,還有第四種類型的區域被稱為Humongous區域。這些區域被設計用來容納大小為標準區域50%或更大的物件。
2. G1中的Young GC
存活的物件被疏散(即複製或移動)到一個或多個倖存者區域。如果達到衰老閾值,一些物件將推廣到老年代區域。
G1中的Young GC同樣會觸發STW
最近進入倖存區域的物件用深綠色表示,最近進入老年區域的用深藍色表示。
總結:
- 堆是分割成區域的單個記憶體空間。
- 年輕代記憶體由一組不連續的區域組成。這使得在需要時可以很容易地調整大小。
- 年輕代垃圾收集或Young GC是STW事件。所有應用程式執行緒都將為此操作停止。
- Young GC使用多個執行緒並行完成。
- 活動物件被複制到新的倖存區或老年代區域。
3. G1中的Old GC階段
階段 | 描述 |
---|---|
(1)初始標記 (STW事件) | 這是一個STW事件。對於G1,初始標記承載在Young GC上。標記倖存者區域(根區域),這些區域可能在老一代中有物件的引用。 |
(2)根區域掃描 | 掃描倖存者區域以查詢對老一代的引用。這是在應用程式繼續執行時發生的。這個階段必須在Young GC發生之前完成。 |
(3)並行標記 | 在整個堆上查詢活躍物件。這發生在應用程式執行時。此階段可被年輕代垃圾收集中斷。 |
(4)最終標記 (STW事件) | 完成堆中活動物件的標記。使用一種稱為snapshot-at-the-beginning(SATB)的演算法,它比CMS收集器中使用的演算法快得多。 |
(5)清除 (STW事件和併發) | 對活動物件和完全自由的區域執行計算(STW);清除(STW);重置空區域並將它們返回到空閒列表(併發) |
(*)複製 (STW事件) | 疏散或者複製存活的物件到新的未使用的區域 |
活動物件的初始標記由年輕代垃圾收集承載。在日誌中,這被記錄為GC pause (young)(inital-mark)
如果發現空區域(如“X”所示),則會在Remark階段立即刪除它們。
空區域被移除並回收,現在要計算所有區域活躍資訊。
G1選擇“活躍資訊”最低的區域,即收集起來速度最快的區域。然後,這些區域與Young GC同時被收集。這在日誌中表示為[GC pause (mixed)]。所以年輕一代和年老一代同時被收集。
所選區域已被收集並壓縮為圖中所示的深藍區域和深綠色區域。
總結:
- 併發標記階段
- 活躍資訊是在應用程式執行時併發計算的。
- 這個活躍資訊確定了在疏散暫停期間哪些區域最好回收。
- 沒有像CMS那樣的sweeping清掃階段。
- 最終標記階段
- 使用Snapshot-the-Beginning(SATB)演算法,該演算法比CMS使用的要快得多。
- 完全空的區域被回收。
- 複製/清理階段
- 年輕代和老年代同時被回收。
- 老年代區域是根據它們的活躍度來選擇的。