以下是對主流 JVM 垃圾回收器的詳細解析,涵蓋?
一、Serial GC(單線程串行回收器)
二、Parallel GC(吞吐量優先回收器)
三、CMS(Concurrent Mark Sweep,低延遲回收器)
四、G1(Garbage-First,區域分代回收器)
五、ZGC(超低延遲回收器)
六、Shenandoah(OpenJDK 低延遲回收器)
?的核心機制、適用場景及橫向對比,幫助理解不同垃圾回收器的設計哲學與性能特點。
一、Serial GC(單線程串行回收器)
核心機制
- 算法:
- 新生代:復制算法(Copying Algorithm),將存活對象從 Eden/Survivor 復制到另一塊 Survivor。
- 老年代:標記 - 整理算法(Mark-Compact),標記存活對象后壓縮內存空間。
- 執行特點:
- 單線程:GC 時需?Stop The World(STW),暫停所有應用線程,全程由一條 GC 線程完成。
- 簡單高效:無線程切換開銷,適合內存較小的環境。
關鍵參數
-XX:+UseSerialGC # 啟用 Serial GC(默認用于 Client 模式)
-XX:SurvivorRatio=8 # Eden:Survivor 比例(默認 8:1)
適用場景
- 嵌入式設備或?單核心服務器(如小型桌面應用)。
- 內存 < 1GB?的場景,STW 時間可控。
優缺點
優點 | 缺點 |
---|---|
簡單可靠,無額外內存開銷 | 單線程導致 STW 時間較長 |
適合內存小的場景 | 無法利用多核 CPU 優勢 |
二、Parallel GC(吞吐量優先回收器)
核心機制
- 算法:
- 新生代:多線程復制算法,并行執行垃圾回收。
- 老年代:多線程標記 - 整理算法(JDK 8 前為 Serial Old,JDK 9+ 為 Parallel Old)。
- 執行特點:
- 多線程并行:通過?
-XX:ParallelGCThreads
?設置線程數,利用多核 CPU 縮短 STW 時間。 - 目標吞吐量:通過?
-XX:GCTimeRatio
?控制 GC 時間占比(默認 99%,即 GC 時間 ≤ 1%)。
- 多線程并行:通過?
關鍵參數
-XX:+UseParallelGC # 啟用 Parallel GC(默認用于 Server 模式)
-XX:MaxGCPauseMillis=100 # 目標最大停頓時間(毫秒,動態調整堆大小)
-XX:GCTimeRatio=99 # 吞吐量目標(1/(1+N),N=99 即吞吐量 99%)
適用場景
- 后臺計算任務(如大數據處理、科學計算),優先保證吞吐量。
- 堆內存中等大小(如 4-8GB),允許較短 STW 但需高持續處理能力。
優缺點
優點 | 缺點 |
---|---|
多線程提升吞吐量 | 停頓時間仍隨堆增大而增長 |
自動調優(自適應策略) | 無法滿足低延遲需求 |
三、CMS(Concurrent Mark Sweep,低延遲回收器)
核心機制
- 算法:
- 標記 - 清除(Mark-Sweep):老年代使用該算法,避免整理內存的 STW 開銷。
- 分代設計:新生代用 Parallel Scavenge(多線程復制),老年代用 CMS 并發回收。
- 執行階段(老年代):
- 初始標記(STW):標記根對象,耗時短。
- 并發標記:與應用線程并行標記可達對象。
- 重新標記(STW):修正并發標記期間的變動,耗時短。
- 并發清除:與應用線程并行清除垃圾對象。
關鍵參數
-XX:+UseConcMarkSweepGC # 啟用 CMS GC
-XX:CMSInitiatingOccupancyFraction=70 # 老年代占用 70% 時觸發 GC
-XX:+CMSParallelRemarkEnabled # 啟用并行重新標記(減少 STW 時間)
適用場景
- 交互式應用(如 Web 服務器、前端服務),需降低 STW 對用戶體驗的影響。
- 堆內存較大(如 8-16GB),但對象存活率較高(老年代占比大)。
優缺點
優點 | 缺點 |
---|---|
老年代并發回收,STW 時間短 | 標記 - 清除導致內存碎片 |
適合低延遲場景 | 并發階段占用 CPU 資源 |
分代設計提升回收效率 | 可能觸發 "Concurrent Mode Failure"(回收速度慢于分配速度) |
四、G1(Garbage-First,區域分代回收器)
核心機制
- 分區(Region)設計:
- 將堆劃分為大小相等的 Region(如 2MB-32MB),每個 Region 可動態扮演 Eden、Survivor、Old 或 Humongous(大對象)。
- 優先回收價值高的區域:通過記錄每個 Region 的垃圾占比,優先處理回收收益最大的區域(Garbage-First 得名)。
- 算法:
- 新生代:多線程復制算法,回收 Eden/Survivor 區域。
- 老年代:并發標記 + 混合回收(部分 Old Region + 新生代),基于標記 - 整理算法。
執行階段
- 初始標記(STW):標記根對象。
- 并發標記:與應用線程并行標記可達對象。
- 最終標記(STW):處理 SATB 日志(Snapshot At The Beginning,記錄并發階段新增引用)。
- 篩選回收(STW):計算各 Region 回收收益,選擇部分 Old Region 與新生代混合回收。
關鍵參數
-XX:+UseG1GC # 啟用 G1 GC
-XX:G1HeapRegionSize=4m # 設置 Region 大小(自動推算默認值)
-XX:MaxGCPauseMillis=200 # 目標最大停頓時間(默認 200ms)
-XX:G1MixedGCCountTarget=8 # 混合回收時最大 Region 數
適用場景
- 大內存(8GB+)?且?需要兼顧吞吐量與低延遲?的場景(如微服務、中間件)。
- 對象分配頻率高(如新生代大對象多),或存在大量中等大小對象(避免進入 Humongous Region)。
優缺點
優點 | 缺點 |
---|---|
分區設計避免內存碎片 | 內存占用高(每個 Region 需元數據) |
可預測的停頓時間 | 并發標記階段耗 CPU 資源 |
混合回收應對老年代回收 | 調優復雜度高于 CMS/Parallel |
五、ZGC(超低延遲回收器)
核心機制
- 著色指針(Colored Pointers):
- 將對象引用的低 4 位用于存儲 GC 狀態(如標記位、重映射狀態),無需修改對象頭,減少內存訪問開銷。
- 讀屏障(Load Barrier):
- 在讀取對象引用時動態修正指針(如對象被移動到新 Region,通過讀屏障獲取新地址)。
- 并發標記 - 整理:
- 全程幾乎無 STW(僅初始標記和再標記有極短停頓,通常 <1ms),支持 TB 級堆內存。
執行階段
- 初始標記(STW):標記根對象,耗時極短。
- 并發標記:與應用線程并行標記可達對象。
- 再標記(STW):處理并發標記期間的引用變動,耗時極短。
- 并發轉移:移動存活對象到新 Region,通過讀屏障修正所有引用。
關鍵參數
-XX:+UseZGC # 啟用 ZGC(JDK 11+)
-XX:ZHeapMaxSize=8t # 最大堆內存(支持 TB 級)
-XX:ZCollectionInterval=1000 # 強制 GC 間隔(毫秒,避免碎片累積)
適用場景
- 超大堆內存(16GB-8TB)且?對延遲敏感?的場景(如金融交易、實時數據處理)。
- 云原生環境(如 Kubernetes 彈性擴縮容),需快速啟動和低停頓。
優缺點
優點 | 缺點 |
---|---|
停頓時間 <10ms,幾乎無感知 | 吞吐量略低于 G1(約 95%) |
支持動態堆大小調整 | 僅 JDK 11+ 可用,需謹慎適配 |
分代設計(JDK 15+)提升年輕代回收效率 |
六、Shenandoah(OpenJDK 低延遲回收器)
核心機制
- 轉發指針(Forwarding Pointer):
- 在對象頭中添加指針,指向對象的新地址(移動后通過該指針修正引用)。
- 布魯姆過濾器(Bloom Filter):
- 快速判斷對象是否已被移動,減少無效的指針掃描,提升并發性能。
- 并發標記 - 復制:
- 與 ZGC 類似,全程并發執行,僅初始標記和最終標記有短暫 STW。
執行階段
- 初始標記(STW):標記根對象。
- 并發標記:與應用線程并行標記可達對象。
- 最終標記(STW):處理漏標的對象,耗時短。
- 并發回收:移動存活對象到新 Region,通過轉發指針更新引用。
關鍵參數
-XX:+UseShenandoahGC # 啟用 Shenandoah(OpenJDK 12+)
-XX:ShenandoahGCMode=主動/被動 # 觸發模式(主動模式基于內存閾值,被動響應分配壓力)
-XX:MaxGCPauseMillis=10 # 目標停頓時間(默認 10ms)
適用場景
- 大內存(8GB-2TB)且?需要 OpenJDK 原生支持?的場景(如開源項目、非商業環境)。
- 對吞吐量要求中等,但需嚴格控制延遲的應用(如消息中間件、實時分析系統)。
優缺點
優點 | 缺點 |
---|---|
停頓時間與 ZGC 相當 | 吞吐量低于 G1(約 90%) |
內存占用低(轉發指針僅占對象頭) | 商業 JDK 需授權(OpenJDK 免費) |
社區活躍,適配性強 | 調優參數較多,需深入理解機制 |
七、橫向對比表格
維度 | Serial GC | Parallel GC | CMS | G1 | ZGC | Shenandoah |
---|---|---|---|---|---|---|
設計目標 | 簡單單線程 | 高吞吐量 | 低延遲(老年代) | 平衡吞吐量與延遲 | 超低延遲(TB 級) | 超低延遲(OpenJDK) |
堆大小推薦 | 小(<1GB) | 中等(4-8GB) | 中大(8-16GB) | 大(8GB+) | 超大(16GB+) | 大(8GB-2TB) |
STW 時間 | 長 | 中等 | 短(老年代并發) | 可控(<500ms) | 極短(<10ms) | 極短(<10ms) |
算法核心 | 復制 + 標記整理 | 并行復制 + 整理 | 并發標記 - 清除 | 分區 + 混合回收 | 著色指針 + 并發整理 | 轉發指針 + 并發復制 |
適用場景 | 嵌入式 / 單核心 | 后臺計算 | Web 服務 | 微服務 / 中間件 | 金融 / 實時數據 | 開源 / OpenJDK 環境 |
JDK 版本 | 全版本 | 全版本 | JDK 1.4+ | JDK 7+ | JDK 11+ | OpenJDK 12+ |
典型參數 | -XX:+UseSerialGC | -XX:+UseParallelGC | -XX:+UseConcMarkSweepGC | -XX:+UseG1GC | -XX:+UseZGC | -XX:+UseShenandoahGC |
八、選擇建議
- 小內存 / 簡單場景:
- 優先選?Serial GC(單核心)或?Parallel GC(多核、需吞吐量)。
- 中等內存 / 低延遲需求:
- 選?CMS(老年代對象多)或?G1(對象分配頻繁、需分代回收)。
- 大內存 / 超低延遲:
- 商業場景選?ZGC(JDK 11+,Oracle/OpenJDK);
- 開源場景選?Shenandoah(OpenJDK 12+,避免授權問題)。
- 云原生 / 彈性擴縮容:
- 優先?ZGC(支持動態堆調整和超大內存)。
九、發展趨勢
- ZGC/Shenandoah 主導未來:逐步替代 G1 成為大內存場景的默認選擇。
- 分代與并發結合:如 ZGC 支持分代(JDK 15+),提升年輕代回收效率。
- 硬件協同優化:利用 CPU 特性(如 AMD 的 MMU 分頁)加速 GC 指針操作。
通過理解不同垃圾回收器的設計 trade-off,可根據具體業務需求(吞吐量、延遲、內存大小)選擇最優方案,或通過組合參數(如 G1 的?-XX:InitiatingHeapOccupancyPercent
)進一步調優。