零基础学习性能测试第二章-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"

相关推荐
张永清2 天前
每周读书与学习->Jmeter中如何使用Bean Shell脚本(一)Bean Shell的简介与安装
性能测试·性能调优·jmeter性能测试·性能分析·性能诊断·每周读书与学习
无聊的小强3 天前
被告警吵醒太多次,我做了个让告警自动修复的监控工具
监控
Derek_Smart3 天前
从一次 OOM 事故说起:打造生产级的 JVM 健康检查组件
java·jvm·spring boot
大道至简Edward3 天前
深入 JVM 核心:一文读懂 Class 文件结构(附 Hex 实战解析)
jvm
weisian1517 天前
JVM--20-面试题6:如何判断对象可以被垃圾回收?
jvm·可达性算法
西岸行者7 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
蚊子码农7 天前
每日一题--JVM线程分析与死锁排查
jvm
悠哉悠哉愿意7 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
可观测性用观测云7 天前
观测云错误中心:帮助团队统一错误视图,定位错误根因并快速修复
监控
别催小唐敲代码7 天前
嵌入式学习路线
学习