天天看點

9 G1 回收器

定義:Garbage First

  • 04年論文釋出
  • 09年JDK 6u14體驗
  • 12年JDK 7u4官方支援
  • 17年JDK9預設

适用場景

  • 同時注重吞吐量和低延遲,預設的暫停目标是200ms
  • 超大堆記憶體,會将堆劃分為多個大小相等的Region,每個區域都可作為伊甸園,幸存區,老年代
  • 9 G1 回收器
  • 整體是标記+整理算法,兩個區域Region之間是複制算法

相關JVM參數

-XX:+UseG1GC JDK8啟用G1GC JDK9就是預設的,不用顯示啟用

-XX:G1HeapRegionSize=size 設定區域大小

-XX:MaxGCPauseMillis=time

9.1 G1 垃圾回收階段

9 G1 回收器

1)Young Collection :新生代的收集階段

如果伊甸園的記憶體滿了,那G1就開始進行垃圾回收,最後把幸存的對象複制到幸存區

9 G1 回收器

再工作一段時間,幸存區的對象有一部分會晉升到老年代,其它年齡小的複制到另外一個幸存區去

9 G1 回收器

2)Young Collection+Concurrent Mark 階段

  • 初始标記就是說我要找到那些根對象。并發标記呢 是從根對象出發,順着他的鍊路去标記 其它對象。
  • 老年代占用空間比例達到門檻值時,會觸發并發标記(不會stw)。門檻值可以通過JVM的一個參數來設定:-XX:InitiatingHeapOccupancyPercent=percent(預設45%)
9 G1 回收器

3)Miaed Collection:混合收集階段

會對E,S,O進行全面的垃圾回收

為了達到一個設定的時間,G1會去老年代裡面在限定時間内找出回收價值最高的老年代。來進行垃圾回收,這樣複制區域小了,就能達到完美理想時間。

為什麼叫Garbage First呢?含義就是優先回收垃圾最多的區域

9 G1 回收器

最終标記就是找出并發标記的漏網之魚。

9.2 垃圾回收器的對比

9 G1 回收器

前兩個觸發full GC的條件都是老年代記憶體不足就觸發。但是後兩個和他們略有差異。

G1裡面老年代記憶體不足,并且你産生新垃圾的速度大于我收垃圾的速度,并發收集失敗,退化為串行收集。那我就全面回收full gc。CMS也一樣。

9.3 Young Collection跨代調用

新生代收集的時候會去找根對象,那根對象有些是在老年代裡面,如果我把老年代全部周遊一遍去查找,那效率是很低的。是以采用一種卡表計數,把老年代的記憶體再進行細分。如果老年代的一個對象引用新生代,那就标記為髒卡。那我以後隻需要關注我标記的對象,減少搜尋範圍,提高效率。新生代這邊有一個Rembered Set 去記錄都有哪些髒卡。将來對新生代垃圾回收的時候,通過這個set去老年代裡面找。

那麼标記髒卡之後,會把髒卡放到一個隊列當中,将來友善維護。

9 G1 回收器

9.4 Remark

9 G1 回收器

黑色将來儲存的,灰色正在處理 ,白色未處理。

垃圾回收時根據黑白來決定該存活還是要當成垃圾。

我們來看這樣一種情況,本來c是和b有強引用關系,但是并發過程中強引用斷開了,是以c被标記為白色。要被回收,但是這時候又有并發線程A強引用C。那不就糟糕了嗎,我c已經被标記為白色了,必須要被幹掉。這樣對A的傷害是很大的,是以有了remark。

9 G1 回收器

 當引用發生改變的時候,我加入一個寫屏障,然後把c放到一個隊列當中,并且變為灰色,當重新标記來了之後,就标記為黑色,就不會被回收掉了。

9 G1 回收器

9.5 G1的優化過程

9 G1 回收器
9 G1 回收器
9 G1 回收器
9 G1 回收器
9 G1 回收器
9 G1 回收器

繼續閱讀