JVM 性能调优参数
一、JVM 参数分类
1.1 标准参数(-)
所有 JVM 实现都必须支持的参数,稳定可靠。
bash
-javaagent # 代理
-classpath # 类路径
-server # 服务器模式
-client # 客户端模式(已废弃)
-version # 查看版本
1.2 -X 参数(非标准但常用)
HotSpot 特有的参数,相对稳定。
bash
-Xms # 初始堆大小
-Xmx # 最大堆大小
-Xmn # 新生代大小
-Xss # 线程栈大小
-Xloggc # GC 日志输出
1.3 -XX 参数(不稳定)
用于调整 JVM 行为,不同版本可能变化。
布尔类型:
bash
-XX:+UseG1GC # 启用 G1 收集器
-XX:-UseSerialGC # 禁用 Serial 收集器
非布尔类型:
bash
-XX:MaxGCPauseMillis=200 # 最大 GC 停顿时间
-XX:MetaspaceSize=256m # 元空间大小
二、堆内存调优
2.1 基本参数
bash
# 推荐设置(生产环境)
-Xms4g # 初始堆 = 最大堆,避免扩容抖动
-Xmx4g
-Xmn1g # 新生代占堆的 1/4 ~ 1/3
-XX:SurvivorRatio=8 # Eden:Survivor = 8:1
计算示例:
ini
堆大小 = 4GB
新生代 = 1GB
Eden = 800MB
From Survivor = 100MB
To Survivor = 100MB
老年代 = 3GB
2.2 对象晋升参数
bash
-XX:MaxTenuringThreshold=15 # 对象在 Survivor 区存活多少次后进入老年代(默认 15)
-XX:PretenureSizeThreshold=1m # 大对象直接进入老年代的阈值
-XX:TargetSurvivorRatio=50 # Survivor 区目标使用率(默认 50%)
2.3 堆溢出诊断
bash
# OOM 时生成堆转储文件
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/path/to/heapdump.hprof
# 分析工具
jmap -histo <pid> # 查看对象分布
MAT (Memory Analyzer Tool) # 图形化分析
三、GC 调优参数
3.1 G1 收集器调优
bash
# 基础配置
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200 # 目标停顿时间(默认 200ms)
-XX:G1HeapRegionSize=4m # Region 大小(默认根据堆大小自动计算)
# 并发线程数
-XX:ConcGCThreads=4 # 并发标记线程数(默认 CPU 核数/4)
# 年轻代大小(可选,G1 会自动调整)
-XX:G1NewSizePercent=10 # 年轻代最小占比(默认 5%)
-XX:G1MaxNewSizePercent=60 # 年轻代最大占比(默认 60%)
# 混合回收
-XX:G1MixedGCLiveThresholdPercent=85 # Old Region 存活率低于此值才回收(默认 85%)
-XX:G1MixedGCCountTarget=8 # 一次 Mixed GC 最多处理的 Old Region 数
3.2 CMS 收集器调优(JDK 8)
bash
-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=70 # 老年代使用率达到 70% 时触发 CMS(默认 92%)
-XX:+UseCMSInitiatingOccupancyOnly # 只使用设定的阈值,不动态调整
-XX:CMSFullGCsBeforeCompaction=5 # 执行 5 次 Full GC 后压缩内存(解决碎片)
-XX:+CMSScavengeBeforeRemark # Remark 前执行 Minor GC,减少停顿
3.3 Parallel 收集器调优
bash
-XX:+UseParallelGC
-XX:MaxGCPauseMillis=200 # 最大停顿时间
-XX:GCTimeRatio=99 # 吞吐量目标(99%,即 GC 时间占 1%)
-XX:ParallelGCThreads=4 # GC 线程数(默认 CPU 核数)
四、元空间调优
bash
# JDK 8+
-XX:MetaspaceSize=256m # 初始元空间大小
-XX:MaxMetaspaceSize=512m # 最大元空间大小
# 监控
jstat -gcmetacapacity <pid> # 查看元空间使用情况
OOM 原因:
- 动态生成大量类(CGLIB、Groovy)
- 应用服务器热部署未清理
- 加载过多第三方库
五、线程相关参数
5.1 栈大小
bash
-Xss1m # 每个线程栈大小(默认 1M,32位系统 320K)
计算最大线程数:
scss
最大线程数 ≈ (可用内存 - 堆大小 - 其他) / Xss
例:8GB 内存,堆 4GB,Xss 1M
最大线程数 ≈ (8GB - 4GB) / 1MB ≈ 4000
5.2 线程栈溢出诊断
bash
# 生成线程转储
jstack <pid> > thread_dump.txt
# 查找死锁
jstack <pid> | grep -A 20 "deadlock"
六、JIT 编译调优
6.1 编译模式
bash
-server # 服务器模式(C2 编译器,优化更激进)
-client # 客户端模式(C1 编译器,启动快,已废弃)
6.2 编译阈值
bash
-XX:CompileThreshold=10000 # 方法调用次数达到阈值后编译(C1)
-XX:TieredStopAtLevel=1 # 分层编译级别(1=C1, 3=C2)
6.3 打印编译信息
bash
-XX:+PrintCompilation # 打印编译信息
-XX:+LogCompilation # 详细编译日志
七、监控与诊断参数
7.1 GC 日志
bash
# JDK 8
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintGCTimeStamps
-Xloggc:/path/to/gc.log
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=5
-XX:GCLogFileSize=10m
# JDK 11+
-Xlog:gc*:file=gc.log:time,uptime:filecount=5,filesize=10m
7.2 JMX 远程监控
bash
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9999
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
7.3 错误处理
bash
# OOM 时执行脚本
-XX:OnOutOfMemoryError="kill -9 %p"
# 生成核心转储
-XX:+UnlockDiagnosticVMOptions
-XX:+CreateCoredumpOnCrash
八、常见调优场景
8.1 Web 应用(低延迟)
bash
-Xms4g -Xmx4g
-Xmn1g
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m
-Xss512k
8.2 批处理(高吞吐)
bash
-Xms8g -Xmx8g
-Xmn2g
-XX:+UseParallelGC
-XX:MaxGCPauseMillis=500
-XX:GCTimeRatio=99
8.3 大内存应用(>32GB)
bash
-Xms64g -Xmx64g
-Xmn16g
-XX:+UseG1GC
-XX:MaxGCPauseMillis=500
-XX:G1HeapRegionSize=16m
-XX:ConcGCThreads=8
九、面试题精选
Q1:如何设置堆大小?为什么建议 -Xms = -Xmx?
bash
-Xms4g -Xmx4g
原因:避免堆扩容/缩容带来的性能抖动和 Full GC。
Q2:新生代和老年代的比例如何设置?
- 新生代占堆的 1/4 ~ 1/3
- 大多数对象朝生夕死,新生代应足够大以容纳短期对象
- 经验值:
-Xmn设置为-Xmx的 1/3
Q3:如何调优 G1 收集器?
- 设置目标停顿时间:
-XX:MaxGCPauseMillis=200 - 调整 Region 大小:
-XX:G1HeapRegionSize - 控制并发线程数:
-XX:ConcGCThreads - 监控 GC 日志,调整
G1MixedGCLiveThresholdPercent
Q4:什么是 Stop-The-World(STW)?
GC 期间暂停所有用户线程,直到 GC 完成。STW 时间越短,应用响应越快。
Q5:如何排查内存泄漏?
- 监控堆内存使用趋势(持续增长不下降)
- OOM 时生成 Heap Dump:
-XX:+HeapDumpOnOutOfMemoryError - 使用 MAT 分析 Dump 文件,查找占用内存最多的对象
- 分析对象引用链,找到泄漏源头
Q6:Full GC 频繁怎么办?
- 检查是否有内存泄漏
- 增大堆大小或新生代
- 调整对象晋升阈值
- 减少大对象创建
- 优化代码,减少对象创建
Q7:如何选择合适的 GC 收集器?
| 场景 | 推荐收集器 |
|---|---|
| 小内存(<4GB) | Serial / Parallel |
| 中等内存(4-8GB),低延迟 | G1 |
| 大内存(>8GB) | G1 / ZGC |
| 超低延迟(<10ms) | ZGC / Shenandoah |
| 批处理(高吞吐) | Parallel |
Q8:JVM 调优的步骤?
- 监控:收集 GC 日志、内存使用、CPU 使用率
- 分析:找出瓶颈(GC 频繁、内存泄漏、CPU 高)
- 调整:修改 JVM 参数
- 验证:对比调整前后的指标
- 迭代:持续优化