-XX:MaxPermSize 設定過小。-XX:PermSize=128M -XX:MaxPermSize=256M;JDK 8+ 已移除永久代,改用 Metaspace(本機記憶體),需調整 -XX:MaxMetaspaceSize。-Xmx 設定過小、大物件直接進老年代觸發頻繁 Full GC。-Xms 物理記憶體 1/64,-Xmx 1/4(32 位 JVM 受限 1.5~3GB)。System.gc()(僅建議,不保證立即執行)。避坑指南:頻繁 Full GC 通常意味著老年代空間不足或記憶體洩漏,需配合工具分析而非盲目增大堆積。
| 參數 | 含義 | 建議值/備註 |
|---|---|---|
-Xms | 初始堆積大小 | 設定等於 -Xmx,避免動態伸縮開銷 |
-Xmx | 最大堆積大小 | 物理記憶體 60%~80%,預留給 OS、Metaspace、線程棧、直接記憶體 |
-Xmn | 新生代大小 | 約 -Xmx 1/4~1/3,過大導致老年代過小頻繁 Full GC |
-XX:PermSize / -XX:MaxPermSize | 永久代初始/最大值 (JDK7-) | 128M / 256M 起步,視類載入量調整 |
-XX:MaxMetaspaceSize | 元空間最大值 (JDK8+) | 建議設定上限,防止無限增長耗盡本機記憶體 |
-Xss | 線程棧大小 | 256K~512K 通常足夠,過大減少可建立線程數 |
-XX:+UseConcMarkSweepGC / -XX:+UseG1GC | GC 收集器選擇 | JDK8 建議 G1;大堆積低延遲首選 ZGC/Shenandoah (JDK11+) |
catalina.sh/bat)JAVA_OPTS="-server -Xms2g -Xmx2g -Xmn512m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m \
-XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/logs/heapdump.hprof"
remove 或設 null,特別是靜態集合。StringBuilder/StringBuffer,避免產生大量中間 String 物件佔滿新生代/常數池。byte[] buf = new byte[request.getContentLength()] 若請求體極大直接 OOM。改用分塊讀取、流式處理、臨時檔案。List 易 OOM。採用游標/分頁/流式處理,處理完一批釋放一批。ThreadLocal、對象池。// 問題代碼
m_totalBytes = m_request.getContentLength(); // 假設 2GB
m_binArray = new byte[m_totalBytes]; // 直接分配 2GB 連續堆積空間 → OOM
// 解決方案:流式處理
try (InputStream in = request.getInputStream();
FileOutputStream out = new FileOutputStream(tempFile)) {
byte[] buffer = new byte[8192];
int len;
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
}
-Xms/-Xmx 設定合理且相等-Xmn)HeapDumpOnOutOfMemoryError 保留現場記憶體調優無銀彈,核心在於理解物件生命週期、選對 GC 收集器、建立可觀測體系。遇到 OOM 先 Dump 再分析,對症下藥才是正道。