线上系统突然变慢,GC 频繁停顿,甚至 OOM 崩溃------这些问题往往和 JVM 参数配置 有关。
很多同学对 JVM 参数的印象是「一堆 -XX: 开头的奇怪配置」,不知道从哪里入手。但其实:
- 80% 的场景只需要几个核心参数
- 常见问题可以通过参数调优解决
- 理解参数能帮你快速定位线上问题
这篇帮你把 JVM 参数彻底搞明白。下面我按「内存参数 → GC 参数 → 诊断参数 → 典型模板」的顺序往下聊。
1. 内存参数:堆、栈、元空间 💾
1.1 堆内存参数
bash
# 堆大小
-Xms512m # 初始堆大小
-Xmx2g # 最大堆大小
-Xms 和 -Xmx 设成一样,避免运行时动态扩展
bash
# 新生代大小
-Xmn256m # 新生代大小(Eden + Survivor)
-XX:NewRatio=2 # 新生代:老年代 = 1:2(老年代是新生代的 2 倍)
bash
# Survivor 区比例
-XX:SurvivorRatio=8 # Eden:Survivor = 8:1(默认)
# 例如:-Xmn512m -XX:SurvivorRatio=8
# 则 Eden = 512m * 8/10 = 409.6m
# 每个 Survivor = 512m * 1/10 = 51.2m
1.2 栈内存参数
bash
# 线程栈大小
-Xss1m # 每个线程的栈大小(默认 1MB)
-Xss512k # 512KB
常见场景:
- 递归调用深:增大
-Xss - 线程数多:减小
-Xss
bash
# 查看默认栈大小
java -XX:+PrintFlagsFinal -version | grep ThreadStackSize
1.3 元空间参数
bash
# Java 8 及之后
-XX:MetaspaceSize=256m # 初始元空间大小
-XX:MaxMetaspaceSize=512m # 最大元空间大小(默认无限制,受物理内存限制)
bash
# Java 7 及之前(永久代)
-XX:PermSize=128m # 初始永久代大小
-XX:MaxPermSize=256m # 最大永久代大小
1.4 直接内存参数
bash
# NIO 直接内存(零拷贝)
-XX:MaxDirectMemorySize=1g # 直接内存最大 1GB
2. GC 参数:收集器与调优 🧹
2.1 收集器选择
bash
# Serial 收集器(单线程)
-XX:+UseSerialGC
# ParNew 收集器(多线程新生代)
-XX:+UseParNewGC
# Parallel 收集器(吞吐量优先)
-XX:+UseParallelGC
-XX:+UseParallelOldGC
# CMS 收集器(低停顿)
-XX:+UseConcMarkSweepGC
# G1 收集器(可预测停顿)
-XX:+UseG1GC
# ZGC 收集器(超低停顿)
-XX:+UseZGC
2.2 CMS 参数
bash
# 启用 CMS
-XX:+UseConcMarkSweepGC
# 触发阈值
-XX:CMSInitiatingOccupancyFraction=80 # 老年代使用 80% 时触发 CMS
# 启用并发预清理
-XX:+UseCMSCompactAtFullCollection # Full GC 时整理碎片
-XX:+UseCMSInitiatingOccupancyOnly # 只按设定阈值触发
2.3 G1 参数
bash
# 启用 G1
-XX:+UseG1GC
# 停顿时间目标
-XX:MaxGCPauseMillis=200 # 目标停顿时间 200ms
# Region 大小
-XX:G1HeapRegionSize=8m # 每个 Region 大小 8MB
# 触发阈值
-XX:InitiatingHeapOccupancyPercent=45 # 堆使用 45% 时触发并发标记
2.4 GC 日志参数
bash
# 打印 GC 详情
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintGCTimeStamps
# 输出到文件
-Xloggc:gc.log
# 完整配置示例
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log
2.5 GC 线程数
bash
# Parallel GC 线程数
-XX:ParallelGCThreads=4
# CMS 并发线程数
-XX:ConcGCThreads=2
3. 调试与诊断参数 🔍
3.1 打印 JVM 信息
bash
# 打印所有 JVM 参数
-XX:+PrintFlagsFinal
# 打印命令行参数
-XX:+PrintCommandLineFlags
3.2 OOM 时自动导出堆 dump
bash
# OOM 时导出堆 dump
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/tmp/heap.hprof
3.3 退出时打印 GC 信息
bash
# 程序退出时打印 GC 摘要
-XX:+PrintGCSummary
3.4 远程调试
bash
# 启用 JMX
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9010
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
4. 典型配置模板 📋
4.1 微服务应用(通用)
bash
java -server \
-Xms512m -Xmx512m \ # 堆大小
-Xmn256m \ # 新生代
-XX:MetaspaceSize=128m \ # 元空间
-XX:MaxMetaspaceSize=128m \
-XX:+UseG1GC \ # 使用 G1
-XX:MaxGCPauseMillis=200 \ # 停顿目标
-XX:+PrintGCDetails \ # 打印 GC 日志
-XX:+PrintGCDateStamps \
-Xloggc:gc.log \
-jar app.jar
4.2 高并发 API 接口
bash
java -server \
-Xms1g -Xmx1g \ # 堆大小 1GB
-Xmn512m \ # 新生代 512MB
-XX:MetaspaceSize=256m \
-XX:MaxMetaspaceSize=256m \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=100 \ # 更短的停顿目标
-XX:InitiatingHeapOccupancyPercent=45 \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/tmp/oom.hprof \
-XX:+PrintGCDetails \
-Xloggc:gc.log \
-jar api.jar
4.3 后台批处理任务
bash
java -server \
-Xms2g -Xmx2g \ # 堆大小 2GB
-Xmn1g \ # 新生代 1GB
-XX:MetaspaceSize=256m \
-XX:MaxMetaspaceSize=256m \
-XX:+UseParallelGC \ # 吞吐量优先
-XX:ParallelGCThreads=8 \
-XX:+UseParallelOldGC \
-XX:+PrintGCDetails \
-Xloggc:gc.log \
-jar batch.jar
4.4 大内存应用(8GB+)
bash
java -server \
-Xms8g -Xmx8g \ # 堆大小 8GB
-Xmn4g \ # 新生代 4GB
-XX:MetaspaceSize=512m \
-XX:MaxMetaspaceSize=512m \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=300 \
-XX:G1HeapRegionSize=16m \ # 更大的 Region
-XX:InitiatingHeapOccupancyPercent=40 \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:+PrintGCDetails \
-Xloggc:gc.log \
-jar large-app.jar
4.5 开发测试环境
bash
java -server \
-Xms256m -Xmx256m \ # 小堆内存
-Xmn128m \
-XX:+UseSerialGC \ # Serial 收集器足够
-XX:+PrintGCDetails \
-Xloggc:gc.log \
-jar app.jar
5. 参数优先级 📊
5.1 参数分类
| 优先级 | 参数类型 | 示例 |
|---|---|---|
| 高 | 内存大小 | -Xms, -Xmx, -Xmn |
| 高 | 收集器选择 | -XX:+UseG1GC |
| 中 | GC 阈值 | -XX:MaxGCPauseMillis |
| 中 | 日志配置 | -XX:+PrintGCDetails |
| 低 | 细节调优 | -XX:G1HeapRegionSize |
5.2 调优顺序
text
1. 先设堆大小(-Xms, -Xmx)
2. 选收集器(-XX:+UseG1GC)
3. 设停顿目标(-XX:MaxGCPauseMillis)
4. 开日志(-XX:+PrintGCDetails)
5. 观察后再微调
6. 常见问题与解决 🔧
6.1 OOM:Java heap space
原因:堆内存不足
解决:
bash
# 增大堆
-Xms2g -Xmx2g
6.2 OOM:Metaspace
原因:元空间不足(类太多)
解决:
bash
# 增大元空间
-XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=512m
6.3 GC 停顿过长
原因:堆太大、收集器不合适
解决:
bash
# 1. 减小堆
-Xms1g -Xmx1g
# 2. 换 G1
-XX:+UseG1GC -XX:MaxGCPauseMillis=200
# 3. 减少对象晋升
-XX:MaxTenuringThreshold=5
6.4 线程栈溢出
原因:递归调用太深
解决:
bash
# 增大栈
-Xss2m
7. 快速参考表 📋
7.1 内存参数
| 参数 | 说明 | 示例 |
|---|---|---|
-Xms |
初始堆大小 | -Xms512m |
-Xmx |
最大堆大小 | -Xmx2g |
-Xmn |
新生代大小 | -Xmn256m |
-Xss |
线程栈大小 | -Xss1m |
-XX:MetaspaceSize |
元空间初始大小 | -XX:MetaspaceSize=256m |
-XX:MaxMetaspaceSize |
元空间最大大小 | -XX:MaxMetaspaceSize=512m |
7.2 GC 参数
| 参数 | 说明 | 示例 |
|---|---|---|
-XX:+UseSerialGC |
Serial 收集器 | -XX:+UseSerialGC |
-XX:+UseParallelGC |
Parallel 收集器 | -XX:+UseParallelGC |
-XX:+UseConcMarkSweepGC |
CMS 收集器 | -XX:+UseConcMarkSweepGC |
-XX:+UseG1GC |
G1 收集器 | -XX:+UseG1GC |
-XX:MaxGCPauseMillis |
停顿目标 | -XX:MaxGCPauseMillis=200 |
-XX:ParallelGCThreads |
GC 线程数 | -XX:ParallelGCThreads=4 |
7.3 诊断参数
| 参数 | 说明 | 示例 |
|---|---|---|
-XX:+PrintGCDetails |
打印 GC 详情 | -XX:+PrintGCDetails |
-XX:+HeapDumpOnOutOfMemoryError |
OOM 时 dump | -XX:+HeapDumpOnOutOfMemoryError |
-XX:HeapDumpPath |
dump 路径 | -XX:HeapDumpPath=/tmp/heap.hprof |
-Xloggc |
GC 日志文件 | -Xloggc:gc.log |
小结
- 内存参数 :
-Xms/-Xmx(堆)、-Xss(栈)、-XX:MetaspaceSize(元空间) - GC 参数 :收集器选择(
-XX:+UseG1GC)、停顿目标(-XX:MaxGCPauseMillis) - 诊断参数 :GC 日志(
-XX:+PrintGCDetails)、OOM dump(-XX:+HeapDumpOnOutOfMemoryError) - 典型模板:微服务用 G1、高并发设停顿目标、批处理用 Parallel
- 调优顺序:先设堆大小 → 选收集器 → 设目标 → 开日志 → 观察微调
下一篇(025)预告:类加载:双亲委派与应用隔离------类加载器原理、打破双亲委派、Tomcat/Spring 类加载器隔离。