JVM 性能调优主要通过监控内存、垃圾回收、线程状态以及 JVM 参数来定位性能瓶颈和异常,并根据分析结果进行优化。常用工具包括 jps
、jinfo
、jstat
、jstack
和 jmap
。下面逐一说明它们的用途、用法及线上案例。本文基于jdk1.8编写,其他版本理念基本相同,供参考。
1️⃣ jps – 查看 Java 进程
jps
用于列出当前系统中运行的 Java 进程,方便定位需要调优的目标进程。
常用命令:
# 列出所有 Java 进程
jps
# 显示进程启动的类全名或 jar 路径
jps -l
# 显示传递给 main 方法的参数
jps -m
# 显示 JVM 启动参数
jps -v
案例:
$ jps 工作中直接用jps查询当前java进程,然后使用jinfo -flags <pid> 查询jvm配置
-m
可以查看 main 方法接收到的参数,适合排查程序启动配置问题。
-v
可以快速确认 JVM 启动参数是否正确。
2️⃣ jinfo – 查看/修改 JVM 参数
jinfo
用于查看或修改正在运行的 JVM 配置,适合线上排查 JVM 参数问题。
常用命令:
# 查看 JVM flags(打印jvm启动参数,包含默认参数)
jinfo -flags <pid>
# 查看指定 Java 进程的系统属性(如 Java 版本、类路径、文件编码、用户信息等
jinfo -sysprops <pid>
- 应用频繁 GC,通过 jinfo flags 确认 jvm 参数是否合理。
3️⃣ jstat – JVM 运行状态监控
jstat
用于监控 JVM 内存使用和 GC 次数和 GC 总耗时,帮助分析 GC 行为及堆内存瓶颈。调优重要的命令。
命令格式:
jstat [option] <pid> [interval(ms)] [count]
<pid>
:Java 进程 IDinterval
:打印间隔(毫秒)count
:打印次数(默认只打印一次)
常用 option:
-gc
:堆内存使用情况和 GC 活动(最最最常用,可以评估程序内存使用及GC压力整体情况)-gccapacity
:各代容量(Young、Old、Metaspace 等)-gcutil
:GC 使用率概览-gcnew
:新生代统计-gcold
:老年代统计
好的,我帮你把jstat -gc <pid> 1
输出解释整理得更完整、更清晰,包含线上常用理解:
jstat -gc 输出字段解释
假设命令:
jstat -gc 12345 1000
每秒打印一次 GC 状态。
字段 | 含义 | 单位/说明 | 线上用途 |
---|---|---|---|
S0C | 第一个幸存区大小 | KB | 判断幸存区配置是否合理 |
S1C | 第二个幸存区大小 | KB | 同上 |
S0U | 第一个幸存区使用量 | KB | 分析对象晋升/回收情况 |
S1U | 第二个幸存区使用量 | KB | 同上 |
EC | Eden 区大小 | KB | 判断新生代容量配置是否合理 |
EU | Eden 区使用量 | KB | 分析 Minor GC 前后对象分布 |
OC | 老年代大小 | KB | 判断 Old 区容量是否足够 |
OU | 老年代使用量 | KB | 分析 Full GC 压力 |
MC | 元空间大小(Metaspace) | KB | 分析类加载/元数据占用 |
MU | 元空间使用量 | KB | 分析 Metaspace 是否接近上限 |
CCSC | 压缩类空间大小 | KB | 对应 HotSpot Compressed Class Pointers |
CCSU | 压缩类空间使用量 | KB | 分析类元数据占用 |
YGC | 新生代 GC 次数 | 次 | 快速判断 Minor GC 频率 |
YGCT | 新生代 GC 总耗时 | 秒 | 分析 Minor GC 成本 |
FGC | Full GC 次数 | 次 | 判断系统是否频繁 Full GC |
FGCT | Full GC 总耗时 | 秒 | 分析 Full GC 对系统影响 |
GCT | GC 总耗时 | 秒 | 总结 GC 对应用吞吐影响 |
注: |
- GC 次数为程序启动后总共次数
- Full GC 越少越好,因为 Full GC 会停顿整个应用线程(Stop-The-World),影响响应和吞吐,Full GC 尽量 小时级甚至更少
- jstat 分析 GC 简洁思路
1️⃣ Young GC
- 触发频率:由 Eden 区对象增长速率和容量决定
- 耗时:
平均耗时 = YGCT / YGC
- 存活对象:每次 Young GC 后 Survivor 和老年代增长量 → 推算对象晋升速率
- 优化目标:存活对象 ≤ Survivor 50%,尽量减少对象进入老年代
2️⃣ Full GC
- 触发频率:由老年代对象增长速率和容量决定
- 耗时:
平均耗时 = FGCT / FGC
- 优化目标:减少 Full GC 次数,延缓老年代填满,使用并发或并行 GC
3️⃣ 分析流程
jstat -gc <pid> <interval>
定期监控- 观察 Eden、Survivor、老年代使用变化
- 结合 YGC/FGC、YGCT/FGCT 计算 GC 频率和平均耗时
- 调整 Young/Old 区大小和 GC 策略,优化停顿
💡 核心原则:
- Young GC 高频、耗时短 → 正常
- Full GC 尽量少、耗时短 → 性能健康
- 监控对象晋升速率 → 预测 Full GC 触发周期
4️⃣ jstack – JVM 线程快照
jstack
用于打印 JVM 线程堆栈,可分析线程阻塞、死锁或长时间执行的问题。
常用命令:
# 打印线程堆栈到thread_dump.log文件
jstack <pid> > thread_dump.log
# 强制打印线程堆栈(进程无响应时)
jstack -F <pid>
# 打印 Java + Native 混合堆栈
jstack -m <pid>
# 显示锁信息
jstack -l <pid>
5️⃣ jmap – JVM 内存分析
jmap
用于分析 JVM 内存使用情况,可生成堆转储文件进一步分析。
常用命令:
# 查看堆内存概要
jmap -heap <pid>
# 生成堆 dump 文件
jmap -dump:format=b,file=heapdump.hprof <pid>
线上案例:
- 应用内存持续增长 → OutOfMemoryError
- 生成堆 dump,使用 JVisualVM 分析,找到占用大量内存的对象,定位内存泄漏。
💡 总结
- jps:快速定位 Java 进程及其启动参数,后面要用进行id。
- jinfo:查看和修改 JVM 参数,用于之后分。
- jstat:GC/堆监控核心工具,快速发现频繁 Full GC 或堆使用异常。
- jstack:线程问题分析利器,排查死锁、阻塞。
- jmap:内存分析和泄漏排查,生成堆 dump 供进一步分析。
通过这套组合工具,能够完整地对 JVM 性能进行诊断、分析和优化,是线上排查和调优的必备利器。