1 ?MixedGC基本過程
在G1GC中,有兩種主要的垃圾回收過程:Young GC和Mixed GC。這兩者都是為了回收堆內存中的垃圾對象,但是他們關注的區域和工作方式有所不同。
Young GC:
Young GC主要負責回收Young Generation(包括Eden區和Survivor區)。大多數新創建的對象都首先在Eden區分配,在一段時間后,如果這些對象仍然存活,它們將被移動到Survivor區或Old區。Young GC通常會頻繁發生,因為大多數對象的生命周期都很短,很快就會變成垃圾可以被回收。
Mixed GC:
與Young GC不同,Mixed GC不僅回收Young Generation,還會回收部分Old Generation。Mixed GC發生的條件是在并發標記周期結束后,也就是說,它會在完成全堆的并發標記之后進行。在Mixed GC中,G1GC會選擇一些可以回收的老年代區域進行清理,這樣可以在不進行Full GC的情況下,盡可能地清理掉一些長時間存活的垃圾對象
在G1GC中,實際上只有YoungGC. 或者說MixedGc是跟隨YoungGC
1 Mixed GC觸發條件:
1)如果堆內存的使用率超過了一個閾值(默認是45%,可以通過-XX:InitiatingHeapOccupancyPercent參數進行調整),那么將會啟動一個并發周期,而Mixed GC則在并發周期結束后開始。
2)老年代的區域已經滿了。G1GC會盡可能地避免Full GC,所以當老年代的區域已經滿了,并且并發標記已經完成,G1GC會觸發Mixed GC以回收老年代的部分區域
? ?老年代的使用率達到 -XX:G1OldCSetRegionThresholdPercent 參數設置的閾值,G1 GC 將會盡管不滿足 G1HeapWastePercent 的要求,也會強制執行 Mixed GC,以防止老年代填滿導致 Full GC
MixedGC階段:
1)初始標記階段
這個過程需要進入Stop the World的,僅僅只是標記一下GC Roots直接能引用的對象,這個過程速度是很快的。如下圖,先停止系統程序的運行,然后對各個線程棧內存中的局部變量代表的GC Roots,以及方法區中的類靜態變量代表的GC Roots,進行掃描,標記出來他們直接引用的那些對象
?
2)并發標記階段
這個階段會允許系統程序的運行,同時進行GC Roots追蹤,從GC Roots開始追蹤所有的存活對象,并對這個過程對象的變化做記錄,比如哪些對象失去了引用,哪些對象是新建的。如下圖所示。(這個階段也是很耗時的,要追蹤全部存活的對象,但跟系統并發運行,影響不大)
3)最終標記階段
這個階段會進入Stop the World,系統程序是禁止運行的,但是會根據并發標記階段記錄的那些對象修改,最終標記一下有哪些存活對象,有哪些是垃圾對象。
4)混合回收階段
? ?計算存活對象數量:在并發標記階段,垃圾收集器會遍歷對象圖并標記存活對象。這個過程可以幫助G1GC了解每個區域的存活對象數量。
? ?計算回收收益:根據每個區域的存活對象數量,G1GC會計算回收收益,即回收某個區域可以釋放多少空間。
? ?選擇回收集合:在計算完回收收益后,G1GC會根據預設的暫停時間目標(例如通過-XX:MaxGCPauseMillis參數設置)來選擇哪些區域應該被包含在回收集合中。這個過程中,G1GC會優先選擇回收收益較高的區域。
? ?這個階段G1允許多次執行混合回收,也就是說先停止系統工作,執行回收,恢復系統運行,再停止系統運行,再回收,再恢復…這么一個流程。每次回收的間隔是由G1自己控制的,回收執行次數可以通過參數-XX:G1MixedGCCountTarget來設置,這個參數默認回收次數是8次,同時有一個參數-XX:G1HeapWastePercent,默認值是整個堆大小5%,就是說當前回收集合內即將空出來的區域大于整個堆的5%,就會立即停止混合回收了。正常默認回收次數是8次,但是可能到了4次,發現空閑Region大于整個堆的5%,就不會再進行后續回收了。
? ?G1HeapWastePercent參數(默認5%),控制了回收集合內總的region的內存大小,
? ? ? ? ?設置太大,
?? ??? ? ? ? ?則經過可能最多8次后還是達不到條件這個閾值。這可能會導致垃圾回收的暫停時間變長,對應用程序的響應時間產生影響。
? ? ? ? ? ? ? 同時,如果 G1 GC 將這種回收效益不高的 region 也加入到回收集合(CSet)中,雖然能回收一些垃圾,但大部分空間仍然被活動對象占據,該 region 的空間利用率并未顯著提高。
? ? ? ? ? ? ? ? ? ?而實際上這些 region 的可回收空間并不多,這就造成了空間的浪費。也導致額外的 CPU 時間被用于回收這些 region
? ? ? ? ? ? ? 如果內存使用效率較低,可能間接導致內存使用率較快達到 IHOP 閾值 ?InitiatingHeapOccupancyPercent,從而導致頻繁觸發并發標記。
? ? ? ? ?設置太小,
?? ??? ? ? ? ? 導致mixed gc 很快就結束。進而導致很多需要回收的region得不到回收,也會影響內存里利用率。能使堆內存使用率更容易達到 -XX:InitiatingHeapOccupancyPercent(IHOP)閾值,從而觸發更頻繁的并發標記。
? ? ? ? ? ? ? ? 如果堆空間使用率持續上升,可能會觸發 Full GC,從而導致更長的垃圾收集暫停時間。
?? ??? ??? ??? ?
?? ??? ??? ??? ?
? ?如果發現老年代中可回收的對象不足以滿足預設的暫停時間目標(由 -XX:MaxGCPauseMillis 參數設置):
? ?G1 GC 可能會提前結束 Mixed GC 狀態,避免不必要的工作,因為繼續執行 Mixed GC 可能無法釋放足夠的空間,卻會消耗更多的 CPU 時間。
? ?
? ? ? ? a)通常是指老年代中可以被回收并釋放的對象數量不足,也就是說,老年代中的大部分對象都還被程序所使用,無法被回收。
?? ? ? ?b)也可能是短壽命的對象,這些對象在年輕代就被回收了,而長壽命的對象(通常會被分配到老年代)相對較少。?
??當老年代中可回收的對象超過預設的暫停時間,G1 GC 會提前結束 Mixed GC,避免回收時間過長,以盡量滿足預設的暫停時間目標。
? 但是,如果經常發生, 這可能導致老年代中未回收的對象增加,從而降低堆內存的使用效率。
? 如果經常出現這種情況,可能需要調整 G1 GC 的配置參數或優化應用代碼以減少老年代中的可回收對象。例如,可以增加-XX:G1OldCSetRegionThresholdPercent和-XX:G1HeapWastePercent的值,以允許 G1 GC 在 Mixed GC 階段回收更多的老年代 Region,或者優化應用代碼以減少長壽命對象的生成。
?
對于已經被加入到 Collection Set (CSet) 中的 region,無論它們是年輕代的還是老年代的,G1 GC 都會在當前的 GC 周期中進行回收。?? ?如果沒有可回收對象,則直接轉YoungGC.
2 ? ? G1GC 新生代是動態的:
-XX:G1NewSizePercent和-XX:G1MaxNewSizePercent,分別為新生代比例的設定數值的下限和上限,默認值分別為5%和60%。G1會根據實際的GC情況(主要是暫停時間)來動態的調整新生代的大小,主要是調整Eden Region的個數。
以下是 G1 GC 動態調整新生代大小的幾個重要因素:
暫停時間目標:G1 GC 通過 -XX:MaxGCPauseMillis 參數設置暫停時間目標。為了盡量滿足這個目標,G1 GC 可以根據前幾次垃圾收集的數據,動態地調整新生代的大小,以影響下一次垃圾收集的暫停時間。
應用程序行為:G1 GC 會根據應用程序的行為,如對象分配速率和對象存活率,動態地調整新生代的大小。對于分配密集型的應用,G1 GC 可能會增大新生代的大小以容納更多的對象。對于對象存活率高的應用,G1 GC 可能會減小新生代的大小以避免存活對象過多導致的復制成本。
并發標記:G1 GC 會盡量在并發標記階段結束后立即觸發一次 Mixed GC。為了保證并發標記能夠在合適的時間結束,G1 GC 會根據堆內存使用率和歷史數據,動態地調整新生代的大小。
因此,新生代的動態性是 G1 GC 實現可預測的停頓時間和高吞吐量目標的一個重要方式。