| GC 類型 | 啟用參數 | 適用場景 | 特點 |
| Serial GC | -XX:+UseSerialGC | 單核、小堆、Client 模式 | 單線程、Stop-the-world 長 |
| Parallel GC | -XX:+UseParallelGC (JDK8 預設) | 多核、批處理、高吞吐 | 並行收集、關注吞吐量 |
| CMS GC | -XX:+UseConcMarkSweepGC | 低延遲、舊版本 | 並發標記清除、JDK 9 棄用、JDK 14 移除 |
| G1 GC | -XX:+UseG1GC (JDK 9+ 預設) | 大堆(4GB+)、混合負載 | 分區整理、可預測停頓、區域化 |
| ZGC | -XX:+UseZGC (JDK 11+) | 超大堆(16TB)、極低延遲 | 彩色指針、亞毫秒停頓、JDK 15 生產就緒 |
| Shenandoah | -XX:+UseShenandoahGC (JDK 12+) | 大堆、低延遲、Red Hat 主導 | 併發整理、無關堆大小停頓 |
選型建議:
- 堆 < 4GB、吞吐優先 → Parallel GC
- 堆 4-16GB、延遲敏感 → G1 GC
- 堆 > 16GB、極致低延遲 → ZGC/Shenandoah
- 調整 GC 後務必同步調大堆內存(-Xmx)
3. 精準配置堆內存分區
# 基礎堆設定
-Xms4g -Xmx4g # 固定堆大小,避免動態伸縮抖動
-XX:NewRatio=2 # 新生代:老年代 = 1:2 (預設)
-XX:SurvivorRatio=8 # Eden:Survivor = 8:1:1
# 元空間 (JDK 8+ 取代 PermGen)
-XX:MetaspaceSize=256m
-XX:MaxMetaspaceSize=512m # 防止元空間無限增長導致 OOM
# 直觀監控參數
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-Xlog:gc*:file=gc.log:time,uptime,level,tags (JDK 9+ 統一日誌)
調優鐵律
- 增大新生代(-XX:NewRatio 減小或 -Xmn 固定)→ 減少 Minor GC 頻率,但增加單次 Minor GC 耗時
- 增大 Survivor(-XX:SurvivorRatio 減小)→ 更多對象留在新生代,減少過早晉升老年代
- 避免 Full GC:Full GC 停頓長,核心目標是讓對象在新生代「朝生夕死」
- 工具輔助:jstat -gcutil、jconsole、VisualVM、Arthas、GCeasy、GCEasy.io 分析 GC 日誌
代碼層面優化(源頭減壓)
1. 禁用手動 System.gc()
// ❌ 禁止:觸發 Full GC,破壞 GC 自適應節奏
System.gc();
// ✅ 正確:信任 GC 自適應策略,或用 -XX:+DisableExplicitGC 禁用顯式 GC
2. 減少大對象直接進老年代
- 大數組、大集合初始化預估大小:
new ArrayList<>(expectedSize)
- 避免循環內大字符串拼接:用
StringBuilder
- 大對象復用:對象池、ThreadLocal 緩存
3. 慎用 finalize()
// ❌ finalize() 增加 GC 負擔、執行時間不可控、可能導致對象復活
@Override protected void finalize() { ... }
// ✅ 替代方案
// - try-with-resources (AutoCloseable)
// - Cleaner / PhantomReference (JDK 9+)
// - 顯式 close()/release() 方法
4. 類加載與元空間控制
- 減少動態代理、CGLIB、JSP 編譯產生的類數量
- 避免
-Xnoclassgc(禁用類卸載),導致元空間洩漏
- RMI/DGC 參數調整:
-Dsun.rmi.dgc.client.gcInterval=3600000 (1小時)
實戰調優清單
- 確認 JDK 版本、GC 類型、堆大小基線
- 開啟 GC 日誌,運行負載測試 30 分鐘+
- 分析:Minor GC 頻率/耗時、Full GC 觸發原因/耗時、老年代增長趨勢
- 調整單一參數(如 -Xmn、SurvivorRatio),重複測試
- 驗證:吞吐量、P99 延遲、GC 停頓分布、內存佔用穩定性
- 文檔化最佳配置,納入部署腳本
總結
JVM 調優無銀彈,**「升級版本 > 選對 GC > 配置分區 > 優化代碼」** 是收益遞減的優先級順序。現代 JDK (11/17/21) 配合 G1/ZGC 已能覆蓋 90%+ 場景,大多數業務只需設定 -Xms=Xmx、開啟 GC 日誌、避免代碼層面反模式即可。複雜場景才需深入分區微調,切記:每次只改一個參數,用數據說話。
- 上一篇文章: JTable 列寬自適應內容完整實作方案
- 下一篇文章: Tomcat 虛擬目錄配置、環境變數設置與 MyEclipse 激活實操指南
Copyright ©
程式碼之家 All Rights Reserved