首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

JVM 內存溢出 (OOM) 兩大經典場景診斷與參數調優全攻略

     編輯:Java 相關知識

OOM 兩大主力戰場

錯誤類型內存區域典型特徵
java.lang.OutOfMemoryError: Java heap space堆對象分配失敗、GC 頻繁、老年代滿
java.lang.OutOfMemoryError: PermGen space永久代 (JDK 7)類加載過多、熱部署、CGLIB 動態代理
java.lang.OutOfMemoryError: Metaspace元空間 (JDK 8+)類元數據超出 MaxMetaspaceSize

場景一:Java Heap Space 診斷與調優

根因分析

  • 堆設定過小(-Xmx 過低)
  • 內存洩漏:集合未清理、靜態引用、監聽器未註銷、ThreadLocal 洩漏
  • 大對象直接進老年代(-XX:PretenureSizeThreshold)
  • GC 策略不當:CMS 碎片、G1 Region 過小

標準調優參數

# 基礎堆設置 (建議 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

Tomcat 具體配置

# 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"

場景二:PermGen / Metaspace 診斷與調優

根因分析

  • 熱部署/重啟頻繁導致類卸載不及時
  • 框架動態生成大量類:Spring AOP (CGLIB)、Hibernate、MyBatis Mapper 代理
  • JSP 預編譯產生大量 Servlet 類
  • JDK 7 永久代默認僅 64MB/82MB,極易滿

JDK 7 永久代調優

# catalina.sh
JAVA_OPTS="$JAVA_OPTS -XX:PermSize=256m -XX:MaxPermSize=512m"

# 關鍵:啟用類卸載 (需 CMS GC)
-XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC

JDK 8+ 元空間調優

# 元空間默認無上限,建議設上限防止佔滿物理內存
-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m

# 壓縮類指針 (64位 JVM 默認開啟)
-XX:+UseCompressedClassPointers

排查工具鏈

  1. jstat:jstat -gcutil 1000 觀察 GC 頻率、各區佔用
  2. jmap:jmap -histo:live | head -30 定位大對象/類
  3. jhat / Eclipse MAT:堆轉儲文件分析洩漏鏈路
  4. Arthas:dashboard、heapdump、classloader 線上診斷
  5. GC 日誌分析:GCEasy、GCViewer 可視化瓶頸

避坑指南

  • 不要盲目增大堆:>8GB 需關注 Full GC 停頓,考慮 G1/ZGC
  • PermGen/Metaspace 設過大:會擠佔堆/直接內存,導致更早 OOM
  • 忽略直接內存:Netty、NIO DirectBuffer 受 -XX:MaxDirectMemorySize 控制
  • 生產環境無 GC 日誌:排查盲區,務必開啟並輪轉

總結

OOM 診斷核心三步:識別區域 → 定位對象/類 → 修正參數或代碼。Heap OOM 側重「對象存活分析 + 分代參數調優」;PermGen/Metaspace OOM 側重「類加載器洩漏 + 動態代理控制 + 元空間上限」。參數調優是治標,代碼修復(洩漏修復、緩存淘汰、對象池化)才是治本。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved