1. 程式人生 > 其它 >JVM-垃圾回收(3)

JVM-垃圾回收(3)

垃圾回收器補充——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使用的要快得多。
    • 完全空的區域被回收。
  • 複製/清理階段
    • 年輕代和老年代同時被回收。
    • 老年代區域是根據它們的活躍度來選擇的。



覺得表達不夠準確,可以點這裡哦