簡稱
- STW —— Stop the World,暫停所有在執行的線程
簡史
- 2004年Sun實驗室第一次發表G1論文
- JDK6U14中第一次作為實驗選項引入
- JDK7中開始作為替換CMS的方案
- JDK9中成為默認的垃圾回收器
- JDK10優化,將其fullGC改為並行: JEP307
- JDK11引入了更新的ZGC,可能會成為G1的潛在替代者
G1特有數據結構和算法
Region
堆仍然有新生代(eden、survivor)、老年代的划分,但是不再要求它們是內存連續的。每個區都由多個Region組成。
部分老年代Region存儲Humongous對象(即下圖的H),這種對象大小大於等於Region的一半。
(圖片來源-Java Hotspot G1 GC的一些關鍵技術)
SATB算法
全稱Snapshot-At-The-Beginning,起始時活對象的快照。在理解SATB前需要先了解以下知識。
三色標記法
CMS和G1的算法都是通過對gc root 進行遍歷,並進行三色標記。標記規則為
- 黑色(black): 節點被遍歷完成,而且子節點都遍歷完成。
- 灰色(gray): 當前正在遍歷的節點,而且子節點(即對象的域)還沒有遍歷。遍歷完所有子節點后,將成為黑色
- 白色(white): 還沒有遍歷到的節點,即灰色節點的子節點。掃描結束仍是白色時會被回收。
並發掃描時,對於白色有兩種情況同時發生時,可能會漏標導致被誤回收:
- 增加了被黑色引用的關系。
- 被灰色下應用,刪除了到它的引用
具體執行過程:https://www.cnblogs.com/javaadu/p/10713956.html
按照R大的說法:CMS的incremental update設計使得它在remark階段必須重新掃描所有線程棧和整個young gen作為root;G1的SATB設計在remark階段則只需要掃描剩下的satb_mark_queue。
RSet
全稱Remember Set,記錄一個Region里的對象被哪些其他Region引用。
相對應地,有另一種輔助數據結構Collection Set(CSet),它記錄了GC要收集的Region集合。GC時只需掃描CSet中各個Rset即可。
(Tips for Tuning the Garbage First Garbage Collector)
更詳細的訪問機制和回收過程這里不再展開,有興趣可以參考后文引用文獻。
Pause Prediction Model
暫停預測模型,G1根據它計算出的歷史數據來預測本次收集需要選擇的Region數量,從而盡量滿足用戶設定的目標停頓時間。
具體算法和公式略,可見Java Hotspot G1 GC的一些關鍵技術
垃圾回收過程
分為以下幾步:
- 初始標記(Initial Mark)—— 標記GC root能直接關聯的對象(短暫STW)
- 並發標記(Concurrent mark)—— GCRootsTracing,從並發標記中的root遍歷,對不可達的對象進行標記,耗時長但可並行
- 最終標記(Final Remark)—— 收集並發標記期間產生的新垃圾(短暫STW),采用了SATB算法比CMS更快
- 篩選回收(Live Data Counting and Evacuation)—— 對各個Region的回收性價比排序,在保證時間可控的情況下清除失活對象,清除Remember Sets
作為對比,CMS的回收過程
- 初始標記(CMS Initial Mark)—— 標記GC root能直接關聯的對象(短暫STW)
- 並發標記(CMS Concurrent Mark)—— GCRootsTracing,從並發標記中的root遍歷,對不可達的對象進行標記
- 重新標記(CMS Remark)—— 修正並發標記期間因為用戶操作導致標記發生變更的對象,有STW
- 並發清除(CMS Concurrent Sweep)
與CMS相比的優勢
- 並發度更高,充分利用CPU多線程 —— CMS對CPU資源敏感,需要占用25%的線程,如果核數小於4更會占用一半的資源。
- 整體上是標記-整理(分代),局部是復制(分Region),運行期不產生碎片 —— CMS是標記-清除,會產生空間碎片和本次回收期間產生導致本次無法回收的浮動垃圾
- 可預測的停頓(基於Region)
參考資料
- 周志明.著 《深入理解Java虛擬機》
2.Java Hotspot G1 GC的一些關鍵技術
3.CMS和G1的回收過程 - 可能是最全面的G1學習筆記
5.G1 SATB和Incremental Update算法的理解