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

Tomcat 內存溢出三大類型診斷與 JVM 參數調優全攻略

     編輯:Java 綜合教學

三大 OOM 類型速查

異常區域典型原因核心參數
Java heap space堆對象過多/大、洩漏、堆太小-Xms, -Xmx
PermGen space (JDK7)永久代類過多、動態代理、熱部署-XX:PermSize, -XX:MaxPermSize
Metaspace (JDK8+)元空間同上,受本地內存限制-XX:MetaspaceSize, -XX:MaxMetaspaceSize
unable to create new native thread線程/本地內存線程數過多、堆佔用過大擠佔本地內存-Xss, -Xmx, 系統 ulimit

1. 堆內存溢出

原理

  • JVM 啟動初始堆 -Xms(物理內存 1/64),最大堆 -Xmx(1/4)。
  • 98% 時間做 GC 且可用堆 <2% → 拋 OOM。
  • 建議 -Xms = -Xmx 避免震蕩,-Xmn(新生代)約 1/4 -Xmx。

參數模板(1G/2G/4G 機器)

# 1G 內存
JAVA_OPTS="-server -Xms800m -Xmx800m -XX:PermSize=64M -XX:MaxPermSize=128m -XX:MaxNewSize=256m -Djava.awt.headless=true"

# 2G 內存 (64位)
JAVA_OPTS="-server -Xms1024m -Xmx1536m -XX:PermSize=128M -XX:MaxPermSize=256m -XX:MaxNewSize=256m"

# 4G+ 生產通用
JAVA_OPTS="-server -Xms2g -Xmx2g -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m -Xmn512m"

配置生效方式

  • startup.sh/bat 啟動:修改 catalina.sh/bat 頭部 JAVA_OPTS 或 CATALINA_OPTS。
  • Windows 服務啟動:修改註冊表 HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\Tomcat Service Manager\TomcatX\Parameters\JavaOptions 追加參數。

2. 永久代/元空間溢出

  • 存放類元數據、常量池(JDK7)、靜態變量。
  • GC 不主動清理,動態生成類(CGLIB、JSP、JDK Proxy)易爆。
  • 方案:增大 PermSize/MaxPermSize (JDK7) 或 MetaspaceSize/MaxMetaspaceSize (JDK8);將公共 JAR 移至 tomcat/shared/lib 減少重複加載。

3. 無法創建本地線程

公式

(MaxProcessMemory - JVMMemory - ReservedOsMemory) / ThreadStackSize = MaxThreads
  • 32 位進程限 2G 用戶空間;分配 1.5G 堆 → 剩 500M 扣除系統 DLL 後約 400M。
  • JDK 1.5+ 默認棧 1M/線程 → 理論極限 ~400 線程。
  • **反直覺結論**:**減小 -Xmx 反而能創建更多線程**。

實際案例

1.5G JVM: (2G - 1.5G - 120M) / 1M ≈ 380 threads
1.0G JVM: (2G - 1.0G - 120M) / 1M ≈ 880 threads

調優建議

  • 減小 -Xmx、-Xss(如 256k)。
  • 遷移 64 位 JVM 突破 2G 限制。
  • 檢查線程池配置,避免無限創建。

運行時內存監控代碼

System.out.println("MAX: " + Runtime.getRuntime().maxMemory()/1024/1024 + "M");
System.out.println("TOTAL: " + Runtime.getRuntime().totalMemory()/1024/1024 + "M");
System.out.println("FREE: " + Runtime.getRuntime().freeMemory()/1024/1024 + "M");
  • maxMemory() = -Xmx 值。
  • totalMemory() = 已向 OS 申請堆大小(含已用+空閒)。
  • freeMemory() = totalMemory() 中未使用部分。

HotSpot 分代堆結構參數

  • 新生代/老年代比:-XX:NewRatio=3 (1:3)
  • 新生代固定:-Xmn64m 或 -XX:NewSize=64m -XX:MaxNewSize=64m
  • 永久代:-XX:PermSize=32m -XX:MaxPermSize=64m
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved