| 錯誤類型 | 內存區域 | 典型特徵 |
|---|---|---|
java.lang.OutOfMemoryError: Java heap space | 堆 | 對象分配失敗、GC 頻繁、老年代滿 |
java.lang.OutOfMemoryError: PermGen space | 永久代 (JDK 7) | 類加載過多、熱部署、CGLIB 動態代理 |
java.lang.OutOfMemoryError: Metaspace | 元空間 (JDK 8+) | 類元數據超出 MaxMetaspaceSize |
# 基礎堆設置 (建議 Xms=Xmx 避免震蕩)
-Xms4g -Xmx4g
# 新生代佔比 (建議 1/3~1/2 堆)
-Xmn1536m
# 幸存區比例 (Eden:S0:S1 = 8:1:1)
-XX:SurvivorRatio=8
# 晉升閾值 (默認 15,可調大減少過早晉升)
-XX:MaxTenuringThreshold=15
# 大對象直接入老年代 (單位字節,默認 0 表關閉)
-XX:PretenureSizeThreshold=1048576
# GC 日誌 (生產必開)
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/logs/gc.log
-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M
# catalina.sh / catalina.bat 中添加
JAVA_OPTS="$JAVA_OPTS -server -Xms4g -Xmx4g -Xmn1536m \
-XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=15 \
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/logs/gc.log \
-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M"
# catalina.sh
JAVA_OPTS="$JAVA_OPTS -XX:PermSize=256m -XX:MaxPermSize=512m"
# 關鍵:啟用類卸載 (需 CMS GC)
-XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC
# 元空間默認無上限,建議設上限防止佔滿物理內存
-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m
# 壓縮類指針 (64位 JVM 默認開啟)
-XX:+UseCompressedClassPointers
jstat -gcutil 1000 觀察 GC 頻率、各區佔用jmap -histo:live | head -30 定位大對象/類dashboard、heapdump、classloader 線上診斷-XX:MaxDirectMemorySize 控制OOM 診斷核心三步:識別區域 → 定位對象/類 → 修正參數或代碼。Heap OOM 側重「對象存活分析 + 分代參數調優」;PermGen/Metaspace OOM 側重「類加載器洩漏 + 動態代理控制 + 元空間上限」。參數調優是治標,代碼修復(洩漏修復、緩存淘汰、對象池化)才是治本。