CMS 垃圾回收器深度剖析:六大階段流程、Card Table 機制、三大缺陷與調優參數
CMS(Concurrent Mark Sweep)以獲取最短停頓時間為目標,採用「並發標記-清除」算法。本文詳細剖析六大階段、預清理與 Card Table 協作機制、三大痛點及調優參數。
六大執行階段
- 初始標記:STW,標記 GC Roots 直接關聯對象。
- 並發標記:與用戶線程並發,GC Roots Tracing 標記所有可達對象。
- 並發預清理:並發,標記新生代晉升、老年代新分配、並發階段被修改的對象(Card Table)。
- 重標記:STW,多線程並行掃描(Rescan),修正並發階段變化。
- 並發清理:並發,清理不可達對象。
- 重置:清理內部狀態,準備下次 GC。
預清理關鍵機制
觸發 Minor GC 減少重標記壓力
- 參數
CMSScheduleRemarkEdenSizeThreshold (默認 2MB) + CMSScheduleRemarkEdenPenetration (50%):Eden 佔用超閾值啟動可中斷預清理,達 50% 或 CMSMaxAbortablePrecleanTime (5s) 中斷進入重標記。
- 若期間發生 Minor GC,新生代存活對象少,重標記 Rescan 只需掃描少量對象,並行效率高(預清理階段已將新生代分塊)。
- 參數
CMSScavengeBeforeRemark:強制重標記前執行 Minor GC,利弊權衡。
Card Table 處理老年代引用變化
- 老年代劃分 512B 塊,Card Table 數組每項對應一塊,標記
dirty card。
- 並發標記階段若對象引用變更,對應 Card 標記 dirty。
- 預清理掃描 dirty card,標記新可達對象,清除 dirty 標記。
- 同樣用於 Minor GC 快速識別老年代引用新生代對象(<1% 場景)。
三大缺陷與應對
| 缺陷 | 原因 | 參數/方案 |
| CPU 佔用高 | GC 線程與用戶線程搶佔 CPU,默認線程數 (CPU+3)/4 | CPU≥4 可接受;CPU<4 可用增量模式 (i-CMS),但已 deprecated |
| 浮動垃圾 | 並發清理階段用戶線程產生新垃圾,本輪無法清理 | CMSInitiatingOccupancyFraction (默認 92%) 提前觸發;動態預測機制 |
| 空間碎片 | 標記-清除不整理,大對象無法分配觸發 Full GC | UseCMSCompactAtFullCollection (默認開啟) Full GC 時壓縮;CMSFullGCsBeforeCompaction 控制頻率 |
總結
CMS 通過並發階段極大縮短 STW,犧牲 CPU 吞吐量換取低延遲。調優核心在於根據應用分配速率設置觸發閾值、啟用壓縮、監控浮動垃圾比例。JDK 9+ 標記 CMS deprecated,推薦遷移至 G1/ZGC。
- 上一篇文章: Java ArrayList 完全指南:動態數組特性、構造方法、常用 API 與遍歷方式
- 下一篇文章: Java 併發編程核心理論:共享性、互斥性、原子性、可見性與有序性深度講解
Copyright ©
程式碼之家 All Rights Reserved