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 事件信息,我们通过诊断工具分析这些数据。它的工作流程很简单:

  1. 监控应用并生成记录文件
  2. 通过两种方式启动监控:
    • 命令行启动应用时启用 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:启用 JFR
  • duration=200s:录制时长 200 秒
  • filename=flight.jfr:输出文件路径

2.3. 使用 jcmd 工具录制

jcmd 是更灵活的替代方案,能对运行中的 JVM 进行诊断操作。基本语法:

jcmd <pid|MainClass> <command> [parameters]

常用命令清单: | 命令 | 功能 | |------|------| | JFR.start | 启动新录制 | | JFR.check | 查看运行中的录制 | | JFR.stop | 停止指定录制 | | JFR.dump | 导出录制数据 |

实操步骤:

  1. 启动应用并获取进程 PID(假设为 128263)
  2. 开始录制:
    jcmd 128263 JFR.start filename=recording.jfr
    
  3. 停止录制:
    jcmd 128263 JFR.stop filename=recording.jfr
    

3. 查看 JFR 录制文件

传统方式使用 Java Mission Control (JMC) 工具分析 .jfr 文件。JMC 提供丰富的可视化分析功能,包括事件时间线、内存分析等:

Java Mission Control 展示飞行记录的仪表盘

4. jfr 命令详解

jfr 命令行工具能解析 .jfr 文件并输出到控制台。相比 JMC 的图形界面,它更适合快速过滤、汇总和生成可读报告。

4.1. 基本用法

jfr 位于 $JAVA_HOME/bin 目录:

$JAVA_HOME/bin/jfr [command] <path>

4.2. 核心命令清单

Java 21 之前已有 5 个子命令,新增的 view 是第六个成员

命令 功能 示例
print 打印录制内容 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 界面对应):

  1. JVM 视图:虚拟机内部指标
  2. 环境视图:宿主机系统信息
  3. 应用视图:应用程序运行数据

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 的可视化输出:

JMC 展示系统进程的界面

命令行输出与图形界面数据完全一致,但更适合自动化分析和远程排查。

7. 总结

本文深入解析了 Java 21 新增的 JFR view 命令,它通过预定义视图实现了命令行级的 JFR 分析能力。我们系统学习了:

✅ 三大类视图的覆盖范围
✅ jfr 和 jcmd 两种使用方式
✅ 输出格式化与定制技巧
✅ 与传统 JMC 工具的对比优势

这个新特性特别适合需要快速诊断、自动化分析或远程排查的场景,是 Java 开发者工具箱的强力补充。完整示例代码可在 GitHub 获取。


原始标题:JFR View Command in Java 21