一、以前收集器的特點
- 年輕代和老年代是各自獨立且連續的內存塊
- 年輕代收集器使用 eden + S0 + S1 進行復制算法
- 老年代收集必須掃描整個老年代區域
- 都是以盡可能的少而快速地執行 GC 為設計原則
二、G1 是什么
- G1 是一種面向服務端的垃圾收集器,應用在多核處理器和大容量內存環境中,在實現高吞吐量的同時,盡可能的滿足垃圾收集器的暫停時間要求。
- 像 CMS 收集器一樣,能與應用程序線程並發執行,
整理空閑空間更快,
需要更多的時間來預測 GC 停頓時間,
不希望犧牲大量的吞吐性能,不需要更大的 JAVA Heap。
- G1 收集器的設計目的是取代 CMS 收集器,同 CMS 相比,
G1 垃圾收集器是一個有整理內存過程的垃圾收集器,不會產生很多內存碎片。
G1 的 Stop The World 更可控,G1 在停頓上添加了預測機制,用戶可以指定期望的停頓時間。
- G1 是在 2012 年才在 jdk.1.7u4 中可以呀用,在 jdk9 中將 G1 變成默認垃圾收集器來代替 CMS。它是一款面向服務應用的收集器。
主要改變是 Eden、Survivor 和 Tenured 等內存區域不再是連續的,而是變成了一個個大小一樣的 region,每個 region 從 1M 到 32M 不等,一個 region 有可能屬於 Eden、Survivor 或者 Tenured 內存區域。
三、特點
- G1 能充分利用多 CPU、多核環境硬件優勢,盡量縮短 STW。
- G1 整體采用標記-整理算法,局部是通過是通過復制算法,不會產生內存碎片。
- 宏觀上看 G1 之中不再區分年輕代和老年代,被內存划分為多個獨立的子區域。
- G1 收集器里面講整個的內存區域混合在一起,但其本身依然在小范圍內要進行年輕代和老年代的區分。保留了新生代和老年代,但她們不在是物理隔離,而是一部分 Region 的集合且不需要 Region 是連續的,也就是說依然會采用不同的 GC 方式來處理不同的區域。
- G1 雖然也是分代收集器,但整個內存分區不存在物理上的年輕代和老年代的區別,也不需要完全獨立的 Survivor to space 堆做復制准備。G1 只有邏輯上的分代概念,或者說每個分區都可能隨 G1 的運行在不同代之間前后切換。
四、底層原理
1、Region 區域化垃圾收集器:最大好處是化整為零,避免全內存掃描,只需要按照區域來進行掃描即可。
2、回收步驟:
3、四步過程:
- 初始標記:標記一下GC Roots能直接關聯到的對象,需要停頓線程,但耗時很短
- 並發標記:是從GC Root開始對堆中對象進行可達性分析,找出存活的對象,這階段耗時較長,但可與用戶程序並發執行
- 最終標記:修正在並發標記期間因用戶程序繼續運作而導致標記產生變動的那一部分標記記錄
- 篩選回收:對各個Region的回收價值和成本進行排序,根據用戶所期望的GC停頓時間來制定回收計划
五、常用配置參數:
-XX:UseG1GC
-XX:G1HeapRegionSize=n:設置G1區域的大小,值是2的冪
-XX:MaxGCPauseMillis=n:設置並行收集最大暫停時間
六、與CMS相比的優勢
- 沒有內存碎片
- 可以精確控制停頓