JMC/JFR/火焰图
诊断的终极组合
JMC(Java Mission Control)、JFR(Java Flight Recorder)和火焰图,是 JDK 提供和配合使用的最强大的诊断工具链。JFR 是数据采集引擎,JMC 是数据可视化工具,火焰图是分析结果的图形化展示。
JFR:飞行记录器
什么是 JFR
JFR(Java Flight Recorder)是 JDK 内置的持续低开销性能分析工具。它像飞机上的黑匣子,持续记录 JVM 运行时的各种事件。
JFR 特点:
✓ 低开销:默认 < 1% CPU 开销
✓ 持续运行:可以在生产环境持续开启
✓ 丰富数据:CPU、内存、GC、线程、IO、锁等
✓ JDK 内置:无需额外安装JFR 的事件类型
JFR 记录的事件分为多个类别:
JFR 事件类别:
├── 虚拟机(VM)
│ ├── 运行日志(vm_info)
│ ├── GC 信息(gc_*)
│ └── 类加载(class_*)
│
├── Java 应用程序
│ ├── 方法分析(profiler)
│ ├── 异常(exception_thrown)
│ └── 线程(thread_*)
│
├── 操作系统
│ ├── CPU 使用(cpu_*)
│ ├── 内存(os_mem_*)
│ └── 网络 IO(socket_*)
│
└── 垃圾回收
├── Minor GC
└── Full GC开启 JFR 录制
方式一:JVM 启动参数
bash
# 开启 JFR,录制数据保存到文件
java -XX:+FlightRecorder \
-XX:StartFlightRecording=dumponexit=true,\
filename=myrecording.jfr,\
settings=profile \
-jar myapp.jar
# 参数说明:
# dumponexit=true → JVM 退出时保存录制
# filename → 输出文件名
# settings → 预置配置(default / profile / template)方式二:JCMD 运行时控制
bash
# 开始录制
jcmd <pid> JFR.start name=myrecording \
settings=profile \
filename=recording.jfr \
duration=60s
# 查看正在运行的录制
jcmd <pid> JFR.check
# 停止录制(生成 .jfr 文件)
jcmd <pid> JFR.stop name=myrecording
# 转储录制数据
jcmd <pid> JFR.dump name=myrecording filename=dump.jfr
# 连续录制(滚动覆盖)
jcmd <pid> JFR.start name=continuous \
settings=default \
maxage=1h \
maxsize=100m \
dumponexit=true \
filename=continuous.jfr方式三:JMC 界面操作
JMC 操作流程:
1. 打开 JMC
2. 在左侧「JVM Browser」中找到目标 JVM
3. 右键 → 启动 Flight Recorder
4. 选择录制模板(default / profile)
5. 设置录制时长或持续录制
6. 录制结束后,自动打开分析视图预置录制模板
| 模板 | 用途 | 开销 | 数据量 |
|---|---|---|---|
| default | 生产环境持续监控 | < 1% | 适中 |
| profile | 详细分析 | < 2-3% | 丰富 |
| template | 自定义模板 | 可调 | 可调 |
bash
# 创建自定义模板
jfr.cmd print --json --categories "gc,profiler" recording.jfrJMC:任务控制中心
JMC 简介
JMC(Java Mission Control)是 JFR 数据的可视化分析工具。JDK 8 自带,JDK 9+ 需要从 jdk.java.net/jmc 下载。
启动 JMC
bash
# JDK 8 自带
jmc
# JDK 9+ 独立版本
/path/to/jmc/bin/jmcJMC 界面
JMC 主界面:
左侧「JVM Browser」:
├── 本地 JVM
│ └── 运行的 Java 进程
└── 远程 JVM(通过 JMX 连接)
└── 远程 Java 进程
右侧「分析视图」:
├── 自动分析(自动分析录制中的问题)
├── 内存(Memory)
├── 代码(Code)
├── 线程(Threads)
├── 文件 I/O(I/O)
└── 环境(Environment)自动分析
JMC 的自动分析会列出发现的问题:
自动分析报告包含:
1. 问题(Problems)
- 高开销方法
- GC 导致的停顿
- 内存泄漏嫌疑人
- 死锁
2. 信息(Info)
- JVM 信息
- 系统信息
- 环境信息
3. 建议(Advisor)
- JVM 参数优化建议
- 代码优化建议内存分析
内存视图展示堆和非堆内存的使用情况:
内存视图包含:
1. GC 摘要
- GC 次数、耗时、原因
2. 堆使用量图表
- 随时间变化的堆使用曲线
3. 对象统计
- 按包/类分组的内存占用
4. TLAB 分配
- 线程本地分配缓冲区统计火焰图(Flame Graph)
火焰图是 JMC 分析结果的一种图形化展示形式。
async-profiler 生成火焰图
async-profiler 是生成火焰图的首选工具:
bash
# 安装 async-profiler
# 下载:https://github.com/async-profiler/async-profiler/releases
# CPU 火焰图
./profiler.sh -d 60 -f cpu.svg <pid>
# -d 60 → 录制 60 秒
# -f cpu.svg → 输出 SVG 文件
# 内存分配火焰图(alloc)
./profiler.sh -d 60 -e alloc -f alloc.svg <pid>
# -e alloc → 监控内存分配
# 锁竞争火焰图
./profiler.sh -d 60 -e lock -f lock.svg <pid>
# -e lock → 监控锁竞争火焰图的阅读方法
火焰图的阅读方式(从下往上):
┌─────────────────────────────────────┐
│ 方法 A │ ← 栈顶(CPU 热点)
│ ┌───────────────────┐ │
│ │ 方法 B │ │
│ │ ┌───────────┐ │ │
│ │ │ 方法 C │ │ │
│ │ │ ┌───────┐ │ │ │
│ │ │ │ 方法 D │ │ │ │
─────────┼─────────┼────┼─┼───────┼──┼────┼───────┼── ← 基线(所有栈的公共起点)
│ │ │ │ JDK │ │ │ │
│ │ │ │ Thread│ │ │ │
│ │ └─┴───────┴──┘ │ │
│ └───────────────────┘ │
└─────────────────────────────────────┘
宽度 → 该方法在采样中出现的次数(越多越宽 = 越热)
高度 → 调用栈的深度
顶层 → CPU 热点方法
颜色:
红色系 → CPU 消耗(默认)
蓝色系 → 内存分配
黄色系 → 锁竞争从 .jfr 生成火焰图
bash
# 方式一:使用 async-profiler 直接分析 PID
./profiler.sh -d 30 -f flamegraph.svg <pid>
# 方式二:使用 JMC 导出数据,再用工具生成火焰图
# JMC → File → Export → CSV
# 使用 FlameGraph 工具生成
# perl flamegraph.pl --collapsed=result.txt > graph.svg
# 方式三:使用 JFR Flamegraphs 脚本
# jfr-flame-graph: https://github.com/chrishanth/flightrecorder/tree/master/jfr-flame-graph
java -jar jfr-flame-graph.jar recording.jfr cpuJFR 事件与火焰图的对应
CPU 火焰图:
采样的调用栈 → 宽度 = CPU 占用比例
Alloc 火焰图:
对象分配的调用栈 → 宽度 = 分配速率
Lock 火焰图:
线程等待锁的调用栈 → 宽度 = 等待时间JFR + JMC + 火焰图 工作流
诊断工作流:
1. 开启 JFR 录制(生产环境持续运行)
└── jcmd PID JFR.start settings=default maxage=1h
2. 发现问题,触发转储
└── jcmd PID JFR.dump filename=issue.jfr
3. 用 JMC 分析 .jfr 文件
└── jmc -open issue.jfr
└── 自动分析 → 定位问题类型
4. 生成火焰图深入分析
└── async-profiler -f flame.svg PID
└── 从火焰图定位热点方法
5. 修复并验证
└── 再次录制,对比改进效果JFR 在生产环境的最佳实践
生产环境 JFR 配置:
1. 默认开启(低开销)
-XX:+FlightRecorder
-XX:FlightRecorderOptions=defaultrecording=true,settings=default
2. 持续录制,滚动覆盖
-XX:+FlightRecorder
-XX:StartFlightRecording=defaultrecording=true,\
settings=default,\
maxsize=100m,\
maxage=1h,\
dumponexit=true
3. OOM 时自动保存
-XX:+FlightRecorder
-XX:FlightRecorderOptions=defaultrecording=true
-XX:StartFlightRecording=\
dumponexit=true,\
filename=oom.jfr,\
settings=profile
4. 安全的 JMX 连接(生产环境)
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9999
-Dcom.sun.management.jmxremote.authenticate=true
-Dcom.sun.management.jmxremote.ssl=true本节小结
JMC/JFR/火焰图核心要点:
| 工具 | 作用 | 特点 |
|---|---|---|
| JFR | 持续低开销的性能数据采集 | < 1% CPU 开销,生产环境可用 |
| JMC | JFR 数据的可视化分析 | 自动分析问题,图形化展示 |
| 火焰图 | 调用栈热点的图形化展示 | 直观定位 CPU/内存热点 |
| async-profiler | 生成火焰图的工具 | 支持 CPU/alloc/lock 等多种模式 |
JFR 是生产环境的诊断利器——低开销、持续运行、丰富数据,配合 JMC 和火焰图,可以精准定位最隐蔽的性能问题。
下一节,我们来看 Arthas 安装/基础指令。
