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

相关推荐
_hermit:1 小时前
【从零开始java学习|第三篇】变量与数据类型的关联
java·学习
知识分享小能手7 小时前
Vue3 学习教程,从入门到精通,Vue 3 + Tailwind CSS 全面知识点与案例详解(31)
前端·javascript·css·vue.js·学习·typescript·vue3
wdfk_prog8 小时前
[Linux]学习笔记系列 -- [arm][lds]
linux·运维·arm开发·笔记·学习
晨非辰9 小时前
#C语言——刷题攻略:牛客编程入门训练(六):运算(三)-- 涉及 辗转相除法求最大公约数
c语言·开发语言·经验分享·学习·学习方法·visual studio
Gloria_niki10 小时前
爬虫与数据分析结合案例学习总结
爬虫·学习·数据分析
一颗正在价投韭菜10 小时前
《范仲淹传》读书笔记与摘要
笔记·学习·范仲淹
遇见尚硅谷11 小时前
C语言:单链表学习
java·c语言·学习
老虎062712 小时前
JavaWeb(苍穹外卖)--学习笔记17(Apache Echarts)
笔记·学习·apache
不修×蝙蝠12 小时前
JVM 运行时全景:从类加载到 GC 的底层原理与调优指南
jvm·基础·详解
SRETALK15 小时前
夜莺开源监控,模板函数一览
运维·监控·自动化运维