JVM调优整理

96 阅读3分钟

1、监控工具

命令行: jps、jstat、jmap、jstack、jcmd

jstat:JVM统计监控工具

jmap:堆内存分析工具

jstack:线程堆栈分析工具

图形化: VisualVM、JConsole、JMC (Java Mission Control)

高级工具:

第三方: Arthas、MAT (Memory Analyzer Tool)、YourKit

GCViewer:GC日志分析工具

Arthas:阿里开源的Java诊断工具

Async Profiler:低开销的性能分析工具

生产环境: Prometheus + Grafana + JMX exporter

2、性能与监控

jps:查看Java进程

jstat:监控JVM统计信息(GC、类加载等)

# 每1秒采集一次,共10次
jstat -gcutil <pid> 1000 10

jmap:内存分析

# 查看堆内存配置
jmap -heap <pid>

# 查看对象分布
jmap -histo <pid>

# 观察内存使用和GC情况
jstat -gcutil <pid> 1000

# 使用Native Memory Tracking:
-XX:NativeMemoryTracking=detail
jcmd <pid> VM.native_memory detail

# 生成堆转储文件分析
jmap -dump:live,format=b,file=heap.hprof <pid>

jstack:线程分析

检查线程数、线程状态、锁竞争情况

# 生成线程快照
jstack <pid> > thread.txt

# 调整线程池大小:
-XX:ParallelGCThreads=8
-Djava.util.concurrent.ForkJoinPool.common.parallelism=8

3、参数调优

堆内存设置

# 初始堆大小(建议设为相同值避免动态调整开销)
-Xms4g

# 最大堆大小
-Xmx4g

# 新生代大小(通常为堆的1/3到1/2)
-Xmn2g

# 元空间大小(Java 8+)
-XX:MetaspaceSize=256m
-XX:MaxMetaspaceSize=256

# 调整Survivor区比,Eden:Survivor=8:1:1
-XX:SurvivorRatio=8

# 调整大对象阈值,大于1MB的对象直接进入Old区
-XX:PretenureSizeThreshold=1024*1024

# 根据堆大小调整,通常1-32M
-XX:G1HeapRegionSize=4M

# 优化年轻代大小,当老年代占用35%时触发Mixed GC
-XX:InitiatingHeapOccupancyPercent=35

GC选择:

# 吞吐量优先(Parallel GC)
-XX:+UseParallelGC
-XX:+UseParallelOldGC

# 低延迟优先(CMS或G1)CMS(JDK8及之前)
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC

# G1(平衡型 JDK9+默认)
-XX:+UseG1GC

4、GC日志配置

-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintHeapAtGC
-XX:+PrintTenuringDistribution
-XX:+UseGCLogFileRotation

-XX:NumberOfGCLogFiles=5
-XX:GCLogFileSize=20M
-Xloggc:/path/to/gc.log

# Java 9+ 使用统一日志
-Xlog:gc*=info:file=/path/to/gc.log:time,uptime,level,tags

5、高级调优

G1调优参数

# 目标最大停顿时间
-XX:MaxGCPauseMillis=200

# 触发并发标记的堆占用率
-XX:InitiatingHeapOccupancyPercent=45

# 保留内存比例
-XX:G1ReservePercent=10

ZGC调优(JDK11+)

# 启用ZGC
-XX:+UseZGC -Xmx16g

# 并发GC线程数
-XX:ConcGCThreads=4

其它

# 逃逸分析优化
-XX:+DoEscapeAnalysis

# 方法内联控制
-XX:MaxInlineLevel=9

# 代码缓存调优
-XX:ReservedCodeCacheSize=240m

# 偏向锁优化
-XX:+UseBiasedLocking

# 压缩Oops
-XX:+UseCompressedOops

6、常见问题与调优

内存问题: 堆内存使用、非堆内存使用、对象分配速率

OOM错误:分析是堆内存还是非堆内存问题

Full GC频繁: 可能内存泄漏或堆大小设置不合理,老年代空间不足或内存泄漏

解决思路:增加堆大小(-Xmx),调整新生代与老年代比例,检查内存泄漏(分析堆转储)

# 新生代:老年代=1:2
-XX:NewRatio=2

# 限制堆外内存使用:
-XX:MaxDirectMemorySize=512m

GC问题: GC频率、GC耗时、各代内存使用情况

Young GC频繁:Eden区过小或对象分配速率过高,新生代太小、对象过早晋升

解决思路:

增大新生代(-Xmn)

调整晋升阈值(-XX:MaxTenuringThreshold)

增加Survivor区(-XX:SurvivorRatio)

  GC停顿时间过长:

选择合适的GC算法,切换到低延迟收集器(G1或ZGC)

# 使用G1收集器,目标最大停顿200ms
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200

# 使用CMS收集器(针对大数据处理场景)
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC

CPU问题: CPU使用率、热点方法

CPU使用率高:查找热点方法或线程死循环

上下文切换频繁:线程数设置不合理