26. java虛擬機總結-垃圾回收器-G1(九)

G1 的回收原理是什麼?爲什麼 G1 比傳統 GC 回收性能好?

爲什麼 G1 如此完美仍然會有 ZGC?

CMS 垃圾回收器的一個極端場景(而且是經常發生的場景)
在發生 Minor GC 時,由於 Survivor 區已經放不下了,多出的對象只能提升(promotion)到老年代。但是此時老年代因爲空間碎片的緣故,會發生 concurrent mode failure 的錯誤。這個時候,就需要降級爲 Serail Old 垃圾回收器進行收集。這就是比 concurrent mode failure 更加嚴重的 promotion failed 問題。一次簡單的 Major GC,竟然能演化成耗時最長的 Full GC。最要命的是,這個停頓時間是不可預知的。

G1( Garbage­First GC)垃圾回收器是如何解決這個問題的?

首先定義一個停頓時間,然後反向推算收集內容,不要求每次都把垃圾清理的乾乾淨淨。我們要求 G1,在任意 1 秒的時間內,停頓不得超過 10ms,這就是在給它制定 KPI。G1 會盡量達成這個目標,它能夠推算出本次要收集的大體區域,以增量的方式完成收集。
-XX:MaxGCPauseMillis=10

什麼是G1垃圾回收器

其他的回收器,都是對某個年代的整體收集,收集時間上自然不好控制。G1 把堆切成了很多份,把每一份當作一個小目標,部分上目標很容易達成。
G1 的全稱是 Garbage­First GC,爲了達成上面制定的 KPI,它和前面介紹的垃圾回收器,在對堆的劃分上有一些不同。

面試題:G1 有年輕代和老年代的區分嗎?

G1 也是有 Eden 區和 Survivor 區的概念的,只不過它們在內存上不是連續的,而是由一小份一小份組成的。這一小份區域的大小( 1M 到 32M 字節之間的一個 2 的冪值數)是固定的,名字叫作小堆區(Region)。小堆區可以是 Eden 區,也可以是 Survivor 區,還可以是 Old 區。所以 G1 的年輕代和老年代的概念都是邏輯上的。

Region 的大小,可以通過參數進行設置:
-XX:G1HeapRegionSize=<N>M

但假如對象太大,一個 Region 放不下了怎麼辦?注意圖中有一塊麪積很大的黃色區域,它的名字叫作 Humongous Region,大小超過 Region 50% 的對象,將會在這裏分配。

那麼,回收的時候,到底回收哪些小堆區呢?是隨機的麼?
這當然不是。事實上,垃圾最多的小堆區,會被優先收集。這就是 G1 名字的由來。

G1 的垃圾回收過程

在邏輯上,G1 分爲年輕代和老年代,但它的年輕代和老年代比例,並不是那麼“固定”,爲了達到 MaxGCPauseMillis 所規定的效果,G1 會自動調整兩者之間的比例。
如果你強行使用 -Xmn 或者 -XX:NewRatio 去設定它們的比例的話,我們給 G1 設定的這個目標將會失效。

G1 的回收過程主要分爲 3 類:

(1)G1“年輕代”的垃圾回收,同樣叫 Minor GC,這個過程和我們前面描述的類似,發生時機就是 Eden 區滿的時候。
(2)老年代的垃圾收集,嚴格上來說其實不算是收集,它是一個“併發標記”的過程,順便清理了一點點對象。
(3)真正的清理,發生在“混合模式”,它不止清理年輕代,還會將老年代的一部分區域進行清理。


在 GC 日誌裏,這個過程描述特別有意思,(1)的過程,叫作 [GC pause (G1 Evacuation Pause) (young),而(2)的過程,叫作 [GC pause (G1 Evacuation Pause) (mixed)。Evacuation 是轉移的意思,和 Copy 的意思有點類似。

這三種模式之間的間隔也是不固定的。比如,1 次 Minor GC 後,發生了一次併發標記,接着發生了 9 次 Mixed GC。

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