Tomcat 記憶體問題 (OOM、GC 頻繁、回應變慢) 是生產環境常見故障。本文介紹三種查看記憶體狀態的方法,解析關鍵指標含義,並提供 JVM 參數調優模板。
conf/tomcat-users.xml 新增角色與用戶
<role rolename="manager-gui"/>
<role rolename="manager-status"/>
<user username="admin" password="securePassword123" roles="manager-gui,manager-status"/>
https://localhost:8080/manager/status,輸入帳密Free memory: 241.80 MB
Total memory: 254.06 MB
Max memory: 508.06 MB
-Xmx 設定值)健康判斷:Free / Max > 20% 為安全;長期 < 10% 需調優或擴容。
# 找到 Tomcat 進程 PID
jps -l | grep Bootstrap
# 每 2 秒輸出一次 GC 統計,共 10 次
jstat -gc 2000 10
# 關鍵欄位解讀
S0C/S1C: Survivor 0/1 區容量
S0U/S1U: Survivor 0/1 區使用量
EC/EU: Eden 區容量/使用量
OC/OU: Old 區容量/使用量
MC/MU: Metaspace 容量/使用量
YGC/YGCT: Young GC 次數/耗時
FGC/FGCT: Full GC 次數/耗時
# 查看堆詳細配置與使用
jmap -heap
# 生成堆轉儲檔 (離線分析)
jmap -dump:live,format=b,file=heap.hprof
# 使用 MAT (Memory Analyzer Tool) 或 JVisualVM 開啟 .hprof 分析洩漏
jcmd VM.flags # 查看 JVM 參數
jcmd GC.class_histogram # 類實例統計 (找大對象)
jcmd GC.heap_dump /tmp/heap.hprof # 生成堆轉儲
| 工具 | 特點 | 適用場景 |
|---|---|---|
| JVisualVM (JDK 內建) | 免費、插件豐富、支援遠程 | 開發測試、基礎分析 |
| JConsole (JDK 內建) | 簡潔、JMX 標準、MBean 操作 | 快速檢視、MBean 調用 |
| Arthas (阿里開源) | 線上診斷、無需重啟、命令豐富 | 生產環境首選 |
| Prometheus + Grafana | 長期存儲、告警、儀表板 | 生產監控體系 |
| MAT (Eclipse Memory Analyzer) | 專業堆轉儲分析、支配者樹、洩漏鏈 | OOM 事後根因分析 |
# 下載啟動
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
# 選擇目標進程後,常用命令
dashboard # 總覽儀表板
memory # 記憶體詳情
heapdump /tmp/heap.hprof # 堆轉儲
thread -n 10 # 前 10 忙碌執行緒
jvm # JVM 參數總覽
gc # GC 統計
# 基礎堆設定 (根據機器記憶體調整,建議不超過物理記憶體 70%)
-Xms4g -Xmx4g # 堆固定大小,避免動態擴縮容震盪
# 新生代/老年代比例 (默認 1:2,可調 1:3 或 1:4 降低 Full GC 頻率)
-XX:NewRatio=3 # Old:New = 3:1
# 元空間 (JDK 8+ 取代永久代)
-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m
# GC 選擇 (根據延遲/吞吐權衡)
# 低延遲首選:G1 (JDK 9+ 默認) / ZGC (JDK 11+) / Shenandoah
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200 # 目標停頓時間
# 高吞吐選擇:Parallel GC
# -XX:+UseParallelGC -XX:ParallelGCThreads=8
# GC 日誌 (生產必開,便於事後分析)
-Xlog:gc*:file=/logs/gc.log:time,uptime,level,tags:filecount=10,filesize=100m
# OOM 時自動生成堆轉儲
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/logs/heapdump.hprof
# 其他推薦
-XX:+UseStringDeduplication # G1 字串去重 (JDK 8u20+)
-XX:+DisableExplicitGC # 禁止 System.gc()
-Dfile.encoding=UTF-8 # 統一編碼
| 現象 | 可能原因 | 排查步驟 |
|---|---|---|
| Heap OOM | 記憶體洩漏 / 堆太小 / 大對象 | 1. MAT 分析堆轉儲 2. 找支配者樹 3. 定位洩漏鏈 |
| Metaspace OOM | 類載入過多 / 類洩漏 (動態代理、JSP) | 1. jcmd GC.class_histogram 2. 檢查動態生成類 |
| Full GC 頻繁 | 老年代空間不足 / 大對象直入 / 內存洩漏 | 1. 調大 -Xmx / NewRatio 2. 檢查大對象分配 3. 分析老年代增長 |
| CPU 飆高 | 頻繁 GC / 死循環 / 鎖競爭 | 1. top -H 找執行緒 2. jstack 分析 3. Arthas thread |
| 回應延遲抖動 | Young GC 停頓 / 安全點同步 | 1. 調整 NewRatio 2. 升級 G1/ZGC 3. -XX:MaxGCPauseMillis |
核心原則:監控先行,數據說話。生產環境必須接入長期監控 (Prometheus/Grafana),建立基線指標,異常時才能快速定位。調優順序:
業務優化 > 參數調優 > 架構擴容。
掌握 Tomcat 記憶體監控與 JVM 調優,是 Java 後端工程師進階的必修課。建議在測試環境完整演練 OOM 觸發、堆轉儲分析、參數調整全流程,生產故障時才能從容應對。