JVM 核心配置與調優指南
一、堆內存與年輕代配置(影響最大)
- 堆內存大小:?在資源允許的前提下,堆內存應盡可能設置得更大。關鍵點:?必須將堆內存的最大值 (
-Xmx
) 和最小值 (-Xms
) 設置為相同值。動態擴容會觸發 Full GC,影響性能。元空間 (-XX:MaxMetaspaceSize
?/?-XX:MetaspaceSize
) 同理,也應設置相同的最大最小值。 - 年輕代占比:?通常建議設置較大的年輕代比例(例如,通過?
-Xmn
?或?-XX:NewRatio
)。在 ZGC 之前的回收器(如 Parallel Scavenge, CMS, G1)中,Young GC 是 STW 的,更大的年輕代可以減少 Young GC 的頻率。
二、垃圾回收器選型策略
- 低延遲不敏感場景(如 OLAP、批處理):?優先選擇?Parallel Scavenge + Parallel Old?組合。這對回收器以最大化吞吐量為設計目標。
- 低延遲敏感場景(如 Web 服務、API):?推薦使用?G1 (Garbage-First)?回收器。雖然《深入理解Java虛擬機》提到小內存下 CMS 可能更優,但作者實踐測試表明,在各種大小內存場景下,G1 的表現通常優于 CMS,更符合現代應用對低延遲的需求。
三、高并發場景下的特殊考量
高并發應用對 GC 停頓極其敏感,應優先選擇低停頓回收器(如 G1),而非高吞吐量回收器(如 Parallel Scavenge/Old)。原因在于:
- Parallel Scavenge/Old 的 Young GC 和 Full GC 都是完全 STW 的。
- G1 的 Mixed GC 部分階段能與用戶線程并發執行,顯著減少 STW 時間。
- 惡性循環風險:?高并發下發生 STW 時,GC 線程(優先級較低)與處理用戶請求的線程競爭 CPU 資源。操作系統可能優先調度用戶請求線程,導致 GC 線程獲得的時間片減少,進而延長 STW 時間。延長的 STW 又會導致請求堆積,進一步增加 GC 壓力(頻率升高、效率降低),形成性能惡化循環。減少 STW 是打破此循環的關鍵。
四、其他重要配置規范
- 棧大小 (
-Xss
):?默認 1MB 通常過大。建議設置為 256k 或更低(如?-Xss256k
),可減少?StackOverflowError
?發生概率,并節省內存。 - 堆/元空間固定大小:?重申第一條關鍵點,
-Xmx
=-Xms
,?-XX:MaxMetaspaceSize
=-XX:MetaspaceSize
,避免擴容觸發 Full GC。 - OOM 時 Dump 日志 (
-XX:+HeapDumpOnOutOfMemoryError
,?-XX:HeapDumpPath
):?發生?OutOfMemoryError
?時自動生成堆轉儲文件,便于事后分析。 - Full GC 前后 Dump (謹慎使用):?通過 JVM 參數或工具(如?
jcmd
)觸發 Full GC 前后的堆轉儲。警告:?Dump 操作消耗大量 CPU 和 I/O 資源,強烈反對在生產環境使用,僅限測試環境診斷。 - 禁止線上遠程調試:嚴禁在生產環境開啟 JVM 的遠程調試端口(如?
-agentlib:jdwp
),存在嚴重安全風險且影響性能。 - 禁止顯式調用?
System.gc()
:?代碼中禁止調用?System.gc()
?或?Runtime.getRuntime().gc()
。這會強制觸發 Full GC,干擾 JVM 自身的 GC 策略,通常導致不必要的性能損耗。 - 避免追求極短停頓時間:?理解 JVM GC 的“不可能三角”(低延遲、高吞吐量、小內存占用)。試圖通過參數(如 G1 的?
-XX:MaxGCPauseMillis
)將目標停頓時間設置得過短,往往會導致 GC?頻率顯著增加,反而降低整體吞吐量。設置合理的目標值更為重要。