1. 引言
Java Flight Recorder (JFR) 是一款强大的 性能分析 和诊断工具,用于监控 JVM 及其上运行的应用程序。作为开发者常用的性能分析利器,它能帮我们实时掌握应用状态和性能表现。
本教程将聚焦 Java 21 为 JFR 新增的 view 命令,这个功能简单粗暴地解决了不少分析痛点。
2. Java Flight Recorder (JFR) 基础
JFR 是 Java 7 引入的低开销应用性能分析框架(最初是实验性功能)。它能帮我们深入理解程序的关键指标,比如 垃圾回收 模式、IO 操作、内存分配 等。
2.1. JFR 是什么?
JFR 在 Java 应用运行时收集 JVM 事件信息,我们通过诊断工具分析这些数据。它的工作流程很简单:
- 监控应用并生成记录文件
- 通过两种方式启动监控:
- 命令行启动应用时启用 JFR
- 使用 jcmd 等诊断工具连接运行中的 Java 应用
记录文件通常保存为 .jfr 格式,后续可通过 Java Mission Control (JMC) 等可视化工具分析,或使用本文重点介绍的 view 命令直接在命令行处理。
2.2. 命令行录制演示
先写个简单程序制造内存溢出场景:
void insertToList(List<Object> list) {
try {
while (true) {
list.add(new Object());
}
} catch (OutOfMemoryError e) {
System.out.println("Out of Memory. Exiting");
}
}
编译程序:
javac -d out -sourcepath JFRExample.java
启动 JFR 录制(关键参数说明):
java -XX:StartFlightRecording=duration=200s,filename=flight.jfr -cp ./out/ com.baeldung.jfrview.JFRExample
✅ 参数解析:
-XX:+FlightRecorder
:启用 JFRduration=200s
:录制时长 200 秒filename=flight.jfr
:输出文件路径
2.3. 使用 jcmd 工具录制
jcmd 是更灵活的替代方案,能对运行中的 JVM 进行诊断操作。基本语法:
jcmd <pid|MainClass> <command> [parameters]
常用命令清单: | 命令 | 功能 | |------|------| | JFR.start | 启动新录制 | | JFR.check | 查看运行中的录制 | | JFR.stop | 停止指定录制 | | JFR.dump | 导出录制数据 |
实操步骤:
- 启动应用并获取进程 PID(假设为 128263)
- 开始录制:
jcmd 128263 JFR.start filename=recording.jfr
- 停止录制:
jcmd 128263 JFR.stop filename=recording.jfr
3. 查看 JFR 录制文件
传统方式使用 Java Mission Control (JMC) 工具分析 .jfr 文件。JMC 提供丰富的可视化分析功能,包括事件时间线、内存分析等:
4. jfr 命令详解
jfr 命令行工具能解析 .jfr 文件并输出到控制台。相比 JMC 的图形界面,它更适合快速过滤、汇总和生成可读报告。
4.1. 基本用法
jfr 位于 $JAVA_HOME/bin
目录:
$JAVA_HOME/bin/jfr [command] <path>
4.2. 核心命令清单
Java 21 之前已有 5 个子命令,新增的 view 是第六个成员:
命令 | 功能 | 示例 |
---|---|---|
打印录制内容 | jfr print --xml flight.jfr |
|
summary | 生成摘要报告 | jfr summary flight.jfr |
metadata | 显示事件元数据 | jfr metadata flight.jfr |
assemble | 合并分块文件 | jfr assemble chunks/ recording.jfr |
disassemble | 拆分录制文件 | jfr disassemble --max-chunks 5 recording.jfr |
4.3. 实战示例
生成录制摘要:
$JAVA_HOME/bin/jfr summary recording.jfr
Version: 2.1
Chunks: 1
Start: 2023-12-25 17:07:08 (UTC)
Duration: 1 s
Event Type Count Size (bytes)
=============================================================
jdk.NativeLibrary 512 44522
jdk.SystemProcess 511 49553
jdk.ModuleExport 506 4921
jdk.BooleanFlag 495 15060
jdk.ActiveSetting 359 10376
jdk.GCPhaseParallel 162 4033
5. JDK 21 的 view 命令
Java 21 新增的 view 命令彻底改变了 JFR 分析方式。它内置 70+ 预定义视图,覆盖 JVM、应用和环境三大维度,无需依赖 JMC 即可完成深度分析。
5.1. 视图分类
视图分为三大类(与 JMC 界面对应):
- JVM 视图:虚拟机内部指标
- 环境视图:宿主机系统信息
- 应用视图:应用程序运行数据
5.2. JVM 视图示例
重点关注虚拟机核心指标:
class-modifications
:类修改统计gc-concurrent-phases
:GC 并发阶段compiler-configuration
:编译器配置gc-configuration
:垃圾回收配置native-memory-committed
:本地内存提交量gc-cpu-time
:GC CPU 耗时compiler-statistics
:编译统计gc-pause-phases
:GC 暂停阶段heap-configuration
:堆配置
5.3. 环境视图示例
系统级监控视图:
cpu-information
:CPU 信息cpu-load
:CPU 负载jvm-flags
:JVM 参数container-configuration
:容器配置network-utilization
:网络使用率system-processes
:系统进程system-properties
:系统属性
5.4. 应用视图示例
应用层分析视图:
exception-count
:异常统计object-statistics
:对象统计allocation-by-thread
:线程分配分析memory-leaks-by-class
:类内存泄漏thread-cpu-load
:线程 CPU 负载thread-count
:线程数量thread-allocation
:线程内存分配
5.5. 命令结构
基础语法:
jfr view [view] <recording file>
通过 jcmd 使用:
jcmd <pid> JFR.view [view name]
⚠️ 支持输出格式化、时间范围筛选等高级参数
6. view 命令实战指南
6.1. 使用 jfr 命令
查看 GC 配置:
jfr view gc-configuration flight.jfr
输出示例:
GC Configuration
----------------
Young GC: G1New
Old GC: G1Old
Parallel GC Threads: 4
Concurrent GC Threads: 1
Dynamic GC Threads: true
Concurrent Explicit GC: false
Disable Explicit GC: false
Pause Target: N/A
GC Time Ratio: 12
6.2. 使用 jcmd 工具
查看系统进程(需运行中 PID):
jcmd 37417 JFR.view cell-height=3 truncate=beginning width=80 system-processes
6.3. 输出格式化技巧
关键参数:
| 参数 | 功能 |
|------|------|
| --width
| 设置列宽 |
| --cell-height
| 设置行高 |
| --verbose
| 显示底层查询 |
| --truncate
| 截断输出位置 |
格式化示例:
jfr view --cell-height 2 --width 100 --truncate beginning --verbose system-processes flight.jfr
System Processes
First Observed Last Observed PID Command Line
(startTime) (startTime) (pid) (commandLine)
-------------- ------------- ----- ----------------------------------------------------------------
23:33:47 23:33:47 453 /Applications/Flycut.app/Contents/MacOS/Flycut
23:33:47 23:33:47 780 ...ions/Grammarly Desktop.app/Contents/Library/LaunchAgents/Gram
marly Desktop Helper.app/Contents/MacOS/Grammarly Desktop Helper
23:33:47 23:33:47 455 /Applications/Grammarly Desktop.app/Contents/MacOS/Grammarly Des
ktop
23:33:47 23:33:47 431 /Applications/JetBrains Toolbox.app/Contents/MacOS/jetbrains-too
lbox
23:33:47 23:33:47 624 /Applications/Safari.app/Contents/MacOS/Safari
COLUMN 'First Observed', 'Last Observed', 'PID', 'Command Line' SELECT FIRST(startTime),
LAST(startTime), FIRST(pid), FIRST(commandLine) FROM SystemProcess GROUP BY pid
Execution: query-validation=10.6 ms, aggregation=241 ms, formatting=121 ms
6.4. 与 JMC 对比
view 命令的设计目标是摆脱对图形工具的依赖。对比 JMC 的可视化输出:
命令行输出与图形界面数据完全一致,但更适合自动化分析和远程排查。
7. 总结
本文深入解析了 Java 21 新增的 JFR view 命令,它通过预定义视图实现了命令行级的 JFR 分析能力。我们系统学习了:
✅ 三大类视图的覆盖范围
✅ jfr 和 jcmd 两种使用方式
✅ 输出格式化与定制技巧
✅ 与传统 JMC 工具的对比优势
这个新特性特别适合需要快速诊断、自动化分析或远程排查的场景,是 Java 开发者工具箱的强力补充。完整示例代码可在 GitHub 获取。