Tomcat JVM 參數配置於 catalina.sh(Windows 為 .bat)。本文通過 7 段配置演進,展示如何分析 GC 日誌、調整堆內存、選擇收集器,最終提升吞吐量。
-Xms50m -Xmx50m -XX:+UseSerialGC -XX:PermSize=50m -XX:MaxPermSize=50m
-Xloggc:/home/log/gc.log -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError
結果:頻繁 Full GC,老年代 34MB 滿載,吞吐量 122.7 req/s,停頓時間長,配置不合理。
-Xms50m -Xmx512m -XX:+UseSerialGC ...
現象:堆穩定在 80M 左右,Full GC 減少。此為尋找穩定堆大小的過渡配置。
-Xms128m -Xmx128m -XX:+UseSerialGC ...
效果:吞吐量提升,GC 次數大幅下降,間隔拉長。
-Xms128m -Xmx128m -XX:+UseParallelGC -XX:+UseParallelOldGC ...
對比:無 GC 壓力時與 Serial GC 差異小;有壓力時並行優勢顯現。
堆 < 80M 觸發頻繁 GC。單核 CPU 下 Parallel GC 無優勢,甚至因線程切換開銷略遜於 Serial GC。結論:單核/弱並行環境首選 Serial GC。
-XX:+UseParNewGC
新生代並行、老年代串行。性能介於全串行與全並行之間。
| 分類 | 參數 | 說明 |
|---|---|---|
| 串行收集器 | -XX:+UseSerialGC | 新生代/老年代均用串行收集器 |
| -XX:SurvivorRatio | Eden 與 Survivor 區比例 | |
| -XX:PretenureSizeThreshold | 大對象直接進老年代閾值 | |
| -XX:MaxTenuringThreshold | 對象晉升老年代最大年齡 | |
| 並行 GC | -XX:+UseParNewGC | 新生代並行收集 |
| -XX:+UseParallelOldGC | 老年代並行收集 | |
| -XX:ParallelGCThreads | GC 線程數,通常等於 CPU 核心數 | |
| -XX:MaxGCPauseMillis | 目標最大停頓時間 | |
| -XX:+UseAdaptiveSizePolicy | 自適應調整新生代大小、 Survivor 比例、晉升年齡 | |
| CMS 收集器 | -XX:+UseConcMarkSweepGC | 新生代並行、老年代 CMS+串行 |
| -XX:ParallelCMSThreads | CMS 線程數 | |
| -XX:CMSInitiatingOccupancyFraction | 老年代佔用率觸發 CMS,默認 68% | |
| -XX:+UseCMSCompactAtFullCollection | Full GC 後進行碎片整理 | |
| -XX:CMSFullGCsBeforeCompaction | 多少次 CMS 後做一次壓縮 | |
| -XX:+CMSClassUnloadingEnabled | 允許類元數據回收 | |
| G1 收集器 | -XX:+UseG1GC | 啟用 G1 |
| -XX:MaxGCPauseMillis | 目標最大停頓 | |
| -XX:GCPauseIntervalMillis | 停頓間隔目標 | |
| TLAB | -XX:+UseTLAB | 開啟線程本地分配緩衝 |
| -XX:+PrintTLAB | 打印 TLAB 分配信息 | |
| -XX:TLABSize | 指定 TLAB 大小 | |
| -XX:+ResizeTLAB | 自動調整 TLAB 大小 | |
| 其他 | -XX:+DisableExplicitGC | 禁用 System.gc() |
| -XX:+ExplicitGCInvokesConcurrent | 顯式 GC 走並發模式 |
性能調優無銀彈,唯有「監測 → 分析 → 調整 → 驗證」的閉環實踐。