首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

JVM 調優總結(九):G1 垃圾回收算法深度解析

     編輯:Java 相關知識

傳統分代 GC 的瓶頸

  • **Full GC 停頓不可控**:大堆(>4GB)下停頓可達秒級,違背實時性要求(百毫秒級)。
  • **並發收集器 (CMS) 缺陷**:整堆掃描、碎片整理困難、浮動垃圾佔 20% 預留空間、易發生 Concurrent Mode Failure 退化為串行 Full GC。

增量收集演進 → G1 (Garbage First)

核心思想:**將堆劃分為大小固定的 Region(默認 1-32MB,共 2048 個)**,按 Region 為單位回收,優先回收**垃圾密度最高**的 Region → **Garbage First**。

G1 設計目標

  • 支持**超大堆**(十幾 GB 到百 GB)。
  • **高吞吐**:多 CPU 並行/並發收集。
  • **準實時**:可配置「N 毫秒內 GC 佔用 ≤ M 毫秒」。
  • 代價:輕微吞吐損失換取停頓可控。

堆佈局與 Region 分類

[Eden Region] [Eden Region] [Survivor Region] [Old Region] [Old Region] ...
   ↑ 年輕代 ↑                    ↑ 老年代 ↑
  • **不再物理連續劃分**新生代/老年代,Region 動態分配角色。
  • **Humongous Region**:專存超大對象(>50% Region 大小),直接歸老年代管理。

四階段回收流程

| 階段 | 動作 | 停頓 | 關鍵點 | |------|------|------|--------| | **1. 初始標記** | 掃描 GC Root → 標記直接可達對象,記錄 TAMS (Top at Mark Start) | **STW** | 極快,借用 Young GC 同步執行 | | **2. 並發標記** | 從 Root 遍歷對象圖,識別存活對象;應用線程並發修改記入 **RSet (Remembered Set)** | 並發 | RSet 記錄跨 Region 引用,避免全堆掃描 | | **3. 最終標記** | 處理 RSet 中剩餘修改,完成標記 | **STW** | 並行多線程處理,通常較短 | | **4. 篩選回收** | **按存活對象大小排序 Region**,優先回收垃圾最多 Region;復制存活對象到新 Region,更新引用 | **STW** | 根據「目標停頓時間」決定回收多少 Region |

關鍵創新點

  1. Region 級別回收:不必全堆掃描,停頓時間可預估、可控。
  2. RSet (Remembered Set):每個 Region 維護「誰引用我」,跨 Region 引用增量更新,掃描只需看 RSet,不掃全堆。
  3. 混合收集:Young GC 同時回收部分 Old Region,避免老年代積壓觸發 Full GC。
  4. 雙向複製清理碎片:回收時將存活對象復制到新 Region,**天然整理碎片**,無需額外壓縮階段。

關鍵參數

  • -XX:+UseG1GC:啟用 G1(JDK 9+ 默認)。
  • -XX:MaxGCPauseMillis=200:目標最大停頓(默認 200ms)。
  • -XX:G1HeapRegionSize=16m:Region 大小(1-32MB,2 的冪)。
  • -XX:InitiatingHeapOccupancyPercent=45:老年代佔比達 45% 觸發並發標記。

展望

JDK 12+ 引入 **ZGC**、JDK 11+ **Shenandoah**,目標**亞毫秒級停頓**,不再依賴分代假設。未來調優將更聚焦於**業務延遲分位點**而非 GC 參數微調。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved