JVM 記憶體溢出三大經典錯誤
| 錯誤類型 | 原因 | 典型場景 | 解決方向 |
java.lang.OutOfMemoryError: Java heap space |
堆積區不足,GC 回收後可用空間 < 2% 且 GC 耗時 > 98% |
大量物件長期存活、記憶體洩漏、堆積設定過小 |
調大 -Xms / -Xmx |
java.lang.OutOfMemoryError: PermGen space |
永久代(類別元資料)滿載,JDK 8 後改為 Metaspace |
大量 JSP 預編譯、熱部署頻繁、載入大量第三方庫 |
調大 -XX:MaxPermSize (JDK7) 或 -XX:MaxMetaspaceSize (JDK8+) |
java.lang.StackOverflowError |
執行緒堆疊溢位,預設 1-2MB |
遞迴過深、大量巢狀方法呼叫 |
修正程式碼邏輯、調大 -Xss |
Tomcat 生產環境記憶體調優實戰
修改 catalina.sh (Linux) 或 catalina.bat (Windows)
在 cygwin=false 那一行之前加入:
JAVA_OPTS="-server -Xms800m -Xmx800m -XX:PermSize=256m -XX:MaxPermSize=512m -XX:MaxNewSize=512m"
關鍵參數說明與最佳實踐
| 參數 | 含義 | 建議值 |
| -server | 啟用 Server VM,多核效能佳,必須放第一個 | 必加 |
| -Xms | 初始堆積大小 | 物理記憶體 1/64 ~ 80%,建議與 -Xmx 相同 |
| -Xmx | 最大堆積大小 | 物理記憶體 80% 上限,不可超過實體記憶體 |
| -Xmn | 新生代大小 | 約 -Xmx 的 1/3 ~ 1/4 |
| -XX:PermSize / MaxPermSize | 永久代初始/最大 (JDK7) | 256m / 512m 起跳 |
| -XX:SurvivorRatio | Eden:Survivor 比例 | 預設 8 (即 8:1:1) |
| -Xss | 單一執行緒堆疊大小 | 256k~512k,視執行緒數調整 |
GC 相關進階參數 (多核環境建議啟用)
-XX:+UseParNewGC # 年輕代平行收集
-XX:+UseConcMarkSweepGC # 老年代 CMS 並發收集,縮短停頓
-XX:ParallelGCThreads=4 # 並行 GC 執行緒數,設為 CPU 核心數
除錯用參數
-verbose:gc
-Xloggc:gc.log
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps