零基础学习性能测试第二章-JVM如何监控

目录

以下是专为零基础设计的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. 步骤1:确认泄漏

    bash 复制代码
    jmap -heap <PID> | grep "used"  # 观察Old Gen使用趋势
  2. 步骤2:生成堆转储

    bash 复制代码
    jmap -dump:live,format=b,file=heapdump.hprof <PID>
  3. 步骤3:分析堆快照

    • 工具:Eclipse MAT / VisualVM
    • 定位技巧:
      • 查找 Retained Heap 最大的对象
      • 检查 Unreachable Objects(不可达对象)
      • 查看 Dominator Tree(支配树)
  4. 常见泄漏模式:

    内存泄漏 静态集合未清理 线程池未销毁 缓存未设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

  1. 压测前准备

    bash 复制代码
    # 开启GC日志
    java -Xlog:gc*:file=gc.log -jar app.jar
    
    # 添加OOM自动dump
    -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp
  2. 压测中监控

    bash 复制代码
    # 实时看板
    jstat -gcutil <PID> 1000  # 每秒刷新
    jcmd <PID> Thread.print    # 定时抓线程
  3. 压测后分析

    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"}')"

八、避坑指南(血泪经验)

  1. 元空间溢出
    -XX:MaxMetaspaceSize=256m# 默认无限制需手动设置

  2. 堆外内存泄漏

    监控 Native Memory Tracking (NMT)

    bash 复制代码
    -XX:NativeMemoryTracking=detail
    jcmd <PID> VM.native_memory summary
  3. G1并发模式失败

    增加 -XX:ConcGCThreads或降低 -XX:InitiatingHeapOccupancyPercent

  4. 线程池耗尽
    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"

相关推荐
阿群今天学习了吗1 小时前
面向对象基础笔记
笔记·学习·算法
是瑶瑶子啦1 小时前
【AlphaFold3】符号说明+Data_pipline学习笔记
人工智能·深度学习·学习
真的想上岸啊1 小时前
学习C++、QT---27(QT中实现记事本项目实现行列显示、优化保存文件的功能的讲解)
c++·qt·学习
余很多之很多2 小时前
借助AI学习开源代码git0.7之四update-cache
git·学习
wyn200011283 小时前
Git学习笔记
笔记·git·学习
Reggie_L4 小时前
JVM-Java
java·jvm·python
rannn_1114 小时前
【Java学习|黑马笔记|Day18】Stream流|获取、中间方法、终结方法、收集方法及其练习
java·笔记·学习
fengye2071615 小时前
板凳-------Mysql cookbook学习 (十二--------2)
学习·mysql·adb
hhj123k5 小时前
渗透作业2
网络·学习