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

发布于:2025-07-24 ⋅ 阅读:(18) ⋅ 点赞:(0)

以下是专为零基础设计的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. 实时监控三件套
# 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日志配置(必须开启!)
// 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:确认泄漏

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

    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问题排查
# 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. 线程数暴涨
# 统计线程数
ps -eLf | grep java | wc -l

# 分析线程类型
jstack <PID> | grep "java.lang.Thread.State" | sort | uniq -c
2. 死锁检测
jstack <PID> | grep -A 10 "deadlock"
3. CPU飙高分析
# 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. 告警规则示例
# 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. 压测前准备

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

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

    # 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)

    -XX:NativeMemoryTracking=detail
    jcmd <PID> VM.native_memory summary
    
  3. G1并发模式失败
    增加 -XX:ConcGCThreads或降低 -XX:InitiatingHeapOccupancyPercent

  4. 线程池耗尽
    jstack中搜索 "pool-1-thread"查看阻塞栈


终极命令:一键式JVM健康检查

#!/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”


网站公告

今日签到

点亮在社区的每一天
去签到