目录
-
-
- 一、JVM监控核心指标(先记这6个)
- 二、必备监控工具与速查命令
-
- [1. **实时监控三件套**](#1. 实时监控三件套)
- [2. **GC日志配置(必须开启!)**](#2. GC日志配置(必须开启!))
- 三、4种内存泄漏快速定位法
- 四、GC性能调优实战
-
- [高频Full GC问题排查](#高频Full GC问题排查)
- 五、线程问题定位技巧
-
- [1. **线程数暴涨**](#1. 线程数暴涨)
- [2. **死锁检测**](#2. 死锁检测)
- [3. **CPU飙高分析**](#3. CPU飙高分析)
- [六、生产级监控方案(Prometheus + Grafana)](#六、生产级监控方案(Prometheus + Grafana))
-
- [1. 监控体系搭建](#1. 监控体系搭建)
- [2. 关键Dashboard指标](#2. 关键Dashboard指标)
- [3. 告警规则示例](#3. 告警规则示例)
- 七、性能测试JVM监控SOP
- 八、避坑指南(血泪经验)
-
以下是专为零基础设计的JVM监控实战指南,聚焦关键指标、常用工具和快速定位问题的方法,可直接应用于性能测试工作:
一、JVM监控核心指标(先记这6个)
指标 | 健康标准 | 异常表现 | 排查工具 |
---|---|---|---|
堆内存使用率 | Old Gen < 70% | 持续增长不释放 → 内存泄漏 | jstat -gc |
Full GC频率 | 0次/小时 | 频繁Full GC (>1次/分钟) | GC日志分析 |
Full GC耗时 | < 1秒 | > 3秒 → STW卡顿 | jstat -gcutil |
Young GC耗时 | < 100ms | > 200ms → 年轻代配置问题 | VisualVM |
线程数 | < 最大线程数80% | 线程数暴涨 → 线程泄漏 | jstack |
CPU占用 | 单进程 < 70% | 持续100% → 死循环/锁竞争 | top + jstack |
二、必备监控工具与速查命令
1. 实时监控三件套
bash
# 1. 监控GC状态 (每2秒刷新)
jstat -gcutil <PID> 2000
# 输出解读:
# S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
# 0.0 0.0 65.0 25.0 95.0 90.0 100 1.5 5 0.8 2.3
# ▶️ E: Eden区使用率 | O: 老年代 | FGC: Full GC次数 | FGCT: Full GC总耗时
# 2. 查看JVM参数 (关键配置)
jcmd <PID> VM.flags
# 3. 生成线程快照 (分析死锁/阻塞)
jstack <PID> > thread_dump.txt
2. GC日志配置(必须开启!)
java
// JDK 8及之前
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/path/to/gc.log
// JDK 11+ (推荐)
-Xlog:gc*:file=/path/to/gc.log:time:filecount=0
日志分析工具:
- GCeasy(在线分析)
grep "Full GC" gc.log
(手动检查Full GC)
三、4种内存泄漏快速定位法
场景:堆内存持续增长不释放
-
步骤1:确认泄漏
bashjmap -heap <PID> | grep "used" # 观察Old Gen使用趋势
-
步骤2:生成堆转储
bashjmap -dump:live,format=b,file=heapdump.hprof <PID>
-
步骤3:分析堆快照
- 工具:Eclipse MAT / VisualVM
- 定位技巧:
- 查找 Retained Heap 最大的对象
- 检查 Unreachable Objects(不可达对象)
- 查看 Dominator Tree(支配树)
-
常见泄漏模式:
内存泄漏 静态集合未清理 线程池未销毁 缓存未设TTL 资源未关闭
四、GC性能调优实战
高频Full GC问题排查
bash
# 1. 检查GC原因
grep -A 5 "Full GC" gc.log
# 典型原因:
# - "Allocation Failure" -> Eden区不足
# - "Metadata GC Threshold" -> 元空间不足
# - "System.gc()" -> 代码调用System.gc()
# 2. 优化方案
| 问题现象 | 参数调整 |
|------------------------|--------------------------|
| Young GC频繁 | -Xmn增加年轻代大小 |
| Full GC后堆内存未释放 | -XX:+UseCMSCompactAtFullCollection |
| CMS GC失败 | -XX:CMSInitiatingOccupancyFraction=70 |
| G1混合GC耗时过长 | -XX:G1MixedGCLiveThresholdPercent=85 |
五、线程问题定位技巧
1. 线程数暴涨
bash
# 统计线程数
ps -eLf | grep java | wc -l
# 分析线程类型
jstack <PID> | grep "java.lang.Thread.State" | sort | uniq -c
2. 死锁检测
bash
jstack <PID> | grep -A 10 "deadlock"
3. CPU飙高分析
bash
# 1. 找高CPU线程
top -H -p <PID> # 记录线程ID(十进制)
# 2. 线程ID转十六进制
printf "%x\n" 12345 # 输出:3039
# 3. jstack中搜索nid=0x3039
jstack <PID> | grep -A 20 "nid=0x3039"
六、生产级监控方案(Prometheus + Grafana)
1. 监控体系搭建
JMX Metrics Dashboard JVM JMX Exporter Prometheus Grafana
2. 关键Dashboard指标
- 内存:Heap/Non-Heap Memory Usage
- GC:GC Pause Duration, GC Count
- 线程:Thread States, Deadlock Detection
- 类加载:Loaded Classes Count
3. 告警规则示例
yaml
# Prometheus告警规则
- alert: FullGCTooFrequent
expr: increase(jvm_gc_pause_seconds_count{gc="PS MarkSweep"}[1m]) > 2
for: 5m
labels:
severity: critical
annotations:
summary: "Full GC频繁 (实例 {{ $labels.instance }})"
七、性能测试JVM监控SOP
-
压测前准备
bash# 开启GC日志 java -Xlog:gc*:file=gc.log -jar app.jar # 添加OOM自动dump -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp
-
压测中监控
bash# 实时看板 jstat -gcutil <PID> 1000 # 每秒刷新 jcmd <PID> Thread.print # 定时抓线程
-
压测后分析
bash# 1. GC分析 cat gc.log | grep "Full GC" | wc -l # 统计Full GC次数 # 2. 内存泄漏检查 jmap -histo:live <PID> | head -20 # 对象直方图 # 3. 生成报告 echo "=== JVM健康报告 ===" echo "Full GC次数: $(grep 'Full GC' gc.log | wc -l)" echo "最大堆内存: $(jstat -gccapacity <PID> | awk '{print $4/1024"MB"}')"
八、避坑指南(血泪经验)
-
元空间溢出
-XX:MaxMetaspaceSize=256m
# 默认无限制需手动设置 -
堆外内存泄漏
监控
Native Memory Tracking (NMT)
:bash-XX:NativeMemoryTracking=detail jcmd <PID> VM.native_memory summary
-
G1并发模式失败
增加
-XX:ConcGCThreads
或降低-XX:InitiatingHeapOccupancyPercent
-
线程池耗尽
jstack
中搜索"pool-1-thread"
查看阻塞栈
终极命令:一键式JVM健康检查
bash
#!/bin/bash
PID=$(jps | grep YourApp | awk '{print $1}')
echo "===== JVM健康检查 ====="
echo "1. GC状态:"
jstat -gcutil $PID 1000 3
echo "2. 堆内存:"
jmap -heap $PID | grep -E "Heap Usage|New Generation"
echo "3. 线程快照:"
jstack $PID | grep "java.lang.Thread.State" | sort | uniq -c
掌握这些技能,你可以在10分钟内 完成JVM基础问题定位,有效支撑性能测试工作。记住核心口诀:
"内存泄漏查堆dump,GC瓶颈看日志,线程问题抓jstack,生产监控上Prometheus"