Java Flight Recorder

2025年5月3日 | 阅读 14 分钟

Java Flight Recorder (JFR) 是一种强大的性能监控和分析工具。它可以在持续的基础上诊断、收集和监控正在运行的 Java 应用程序,即使在发生灾难性故障时也能如此。它集成在 JVM 中。该工具提供了一个强大的 GUI 来进行应用程序性能分析。它被用于高负载的生产环境应用程序,如性能分析、黑盒分析支持调试。在本节中,我们将详细讨论Java Flight Recorder。此外,我们还将了解它的概念、用途、架构、JMCJFR基本命令

什么是 Java Flight Recorder (JFR)?

它首次引入于JDK 1.7。它的功能是用Java编写的。它是一种应用程序诊断工具,可以捕获JVM应用程序数据。这些数据包括垃圾回收、同步、编译器、CPU使用率、异常、I/O 等。它还提供了一个基于采样的分析器。借助分析器,我们可以获得准确的数据和低开销。它使用循环缓冲区来存储数据。

Java Flight Recorder

上图描绘了循环飞行记录缓冲区的概念。新数据不断添加到缓冲区,旧数据被移除。

JFR 工具不能独立使用。因此,它与 Java Mission Control (JMC) 一起使用。JMC 工具包含一个插件,允许我们可视化 JFR 收集的数据。除了 JFR,JDK 还提供了一些其他工具用于监控和分析。

  • Java VisualVM
  • JConsole
  • Java Mission Control
  • 诊断命令工具

请注意,Java VisualVM 过去是 Oracle 和 Open JDK 发行版的一部分。自 Java 9 起,Java VisualVM 已被移除。下图描绘了 JFR 的演变。

Java Flight Recorder

注意:如果要在生产环境中使用 JFR 工具,需要商业许可证。

Java Flight Recorder 的优点

与 JFR 类似,也有一些其他工具可用。但 JFR 相较于它们有一些优势,如下所示:

  • 实时分析:它提供 Java 应用程序的实时分析,并且可以与其他工具集成。
  • 提供增强数据:JFR 使用精细的数据模型。这使得交叉引用和过滤事件以提供连贯的数据更加容易。
  • 降低所有权成本:通过减少诊断和故障排除时间来降低成本。因此,它降低了运营成本并提高了系统效率。
  • 允许第三方事件提供商:JFR 还可以监控 WebLogic Server 和其他产品等第三方应用程序。

Flight Recorder 的用途

  • 黑盒分析:JFR 将应用程序信息持续添加到循环缓冲区。当检测到异常时,可以访问缓冲区收集的信息以找出原因。
  • 性能分析:性能分析是一种动态程序分析。这意味着它会测量与性能相关的问题。JFR 执行以下两种性能分析:
    1. CPU 性能分析:分析应用程序的性能。
    2. 内存性能分析:分析应用程序的内存。
    性能分析信息包含垃圾回收详细信息、内存、锁分析、时间复杂度、函数调用的频率和持续时间以及线程采样。性能分析信息有助于应用程序优化。它提高了应用程序的延迟和吞吐量。
  • 支持和调试:当联系 Oracle 支持部门帮助诊断 Java 应用程序问题时,JFR 收集的数据可能非常重要。

JFR 架构

JFR 架构包含以下内容:

JFR 包含一个生成记录的运行时引擎。运行时引擎有两个组件:AgentProducers

Agent 的工作是处理缓冲区、磁盘和 MBeans 等。它提供了一个用 C 和 Java 代码编写的动态库。Producers 将数据写入缓冲区。

JFR 插件使我们能够使用 JMC。我们可以通过 GUI 轻松地启动、停止和配置记录。

Java Flight Recorder

JFR 组件

JFR 有两个主要概念:EventDataflow。让我们简要讨论一下。

JFR 事件

在 JFR 中,一切都是一个事件。它收集 JVM 中发生的事件以及应用程序日志。事件代表 JVM 和应用程序的状态。JFR 收集的信息分为两部分:HeaderPayload

Java Flight Recorder

Header 包括大小、事件 ID结束时间。Payload 包含特定于事件的数据。除此之外,它还包括开始时间、线程 ID堆栈跟踪 ID,但这些是可选的 Payload。记录事件时,必须定义以下两项:

  • Producer:基本上,Producer 是 JFR 捕获的事件的元数据和命名空间。必须将事件类型注册到 Producer。如果 Producer 不再被引用,事件类型将被移除。但这是一种不良的做法。如果要创建 Producer,只需像下面这样创建一个 Producer 实例:
  • Event Type:在 Event Type 中,我们定义用于描述事件的元数据以及可用的属性(数据)。
事件元数据
对于事件名称、路径、描述
对于 Payload名称、类型、描述、Content-Type

Content-Type 描述了值的语义。它在 UI 中正确表示值。

Content Type表示
字节7 MB
百分比56%
地址0x22CDA321
毫秒20ms
纳秒4567ns

因此,事件收集了应用程序的非常高层级的数据。我们应该始终记录实际需要的事件,因为这可以最大限度地减少开销。我们还可以按类型、名称持续时间过滤事件。

事件类型

JFR 收集以下三种类型的事件:

Java Flight Recorder
  • 即时事件:这些事件立即发生。即时事件的示例是线程启动。
  • 持续时间事件:这些事件具有开始结束时间。持续时间事件的示例是垃圾收集器。
  • 可请求事件:这些事件的时间由用户配置。它以固定的间隔记录。它也称为采样事件。可请求事件的示例是每秒的 CPU 使用率。

创建事件

我们可以使用以下代码片段创建自己的事件。

让我们为一些常量创建一个事件。

在上面的代码中,我们还可以做一些额外的事情,为应用程序提供一些有用的提示。为此,我们使用注解

JFR 注解

下表列出了一些有用的注解。还有一些其他注解可以在Javadoc中找到。

注解描述默认
@Name它描述了事件名称。这是一个类级别的注解。com.oracle.javatpoint.EventName
@Label它用于注解字段,如变量和常量。不适用
@Description它提供关于某事物的详细描述(大约 1 到 2 行)。不适用
@Category它指定一个事件属于哪个类别。不适用
@Threshold它指定事件的最小持续时间。0ns
@Enabled它控制事件是否应该启用。true(已启用)
@StackTrace它允许我们控制(启用/禁用)堆栈跟踪。true(已启用)

JFR 数据流

事件批量从 JVM 和 Java 应用程序收集数据。它从两者收集数据并将其存储在小的线程本地缓冲区中。然后,当线程缓冲区达到极限时,数据会被刷新到全局缓冲区(或内存中)。类似地,当全局缓冲区达到极限时,旧数据将被丢弃。之后,数据被刷新到存储库。

Java Flight Recorder

因此,它的设计足够快,不会抑制程序。所有事件的数据都存储在flight.jfr文件中,因为磁盘 I/O 操作成本更高。该机制更复杂,因为同时应用程序可能具有多个具有不同选项的注册进程。

注意:不可能在两个地方获取数据。这意味着数据块将在磁盘或内存(缓冲区)中可用,但不会同时存在。这避免了数据重叠。

因此,使用 JFR,我们在 JFR 文件中获得的平均数据比请求的要多。请记住,数据可能按时间顺序排列,也可能不按时间顺序排列。下图描绘了 JFR 中事件的数据流。

运行 Java Flight Recorder

配置 JFR

在启用 JFR 工具之前,请确保您使用的是同一 JDK 发行版中的 javac、java、JFR、JMC 和 jcmd 工具。如果您安装了不同版本的 Java,它可能会提供错误的数据。

启用 JFR

我们知道这是一个商业功能。因此,在运行它之前,我们需要解锁商业功能。可以使用以下标志来解锁:

其中DemoApp是应用程序名称。

注意:如果您使用的是 Java 11,则无需激活其商业功能。

启动 JFR

高级配置

预记录会话
数据的最大年龄maxage=<time>
最大存储大小maxsize=<size>
全局设置 (-XX:FlightRecorderOptions)
最大堆栈跟踪深度stackdepth=<n> (默认 64)
退出时保存记录dumponexit=true
日志记录loglevel=[ERROR|WARN|INFO|DEBUG|TRACE]
存储库路径repository=<path>

有三种运行 JFR 的方法:

  • 使用 JMC 中的 JFR 插件
  • 使用命令行选项
  • 使用诊断命令

使用 JMC 中的 JFR 插件

我们可以使用 JFR 插件创建记录。它已集成到 JMC 中。请按照以下步骤创建记录:

  • 右键单击 JVM,然后选择“Start Flight Recording”。如果它是远程 JVM,您需要先创建一个“JVM Connection”。
  • 选择记录类型:固定时间/连续
  • 选择“Event Settings”模板
  • 修改选定的飞行记录模板的事件选项(可选)
  • 修改事件详细信息(可选)

使用命令行选项

当我们在启动应用程序时使用 java 命令,我们也可以启用 JFR、配置它并开始记录。

  1. -XX:+|-FlightRecorder
  2. -XX:FlightRecorderOptions
  3. -XX:StartFlightRecording

注意:命令行选项在 JDK 的商业许可证中可用。如果您想使用它,需要使用以下选项启用它:

使用诊断命令

以下四个诊断命令与 JFR 相关:

  1. JFR.start
  2. JFR.check
  3. JFR.stop
  4. JFR.dump

JFR.start:该命令启动飞行记录。下表描述了可用于该命令的参数。

参数描述值类型默认
name记录名称String-
settings服务器端模板String-
defaultrecording启动默认记录BooleanFalse
delay延迟启动记录时间0s
duration记录持续时间时间0s(表示“无限期”)
filename生成的记录文件名String-
compressionGZip 压缩生成的记录文件BooleanFalse
maxage缓冲区数据的最大年龄时间0s(表示“无年龄限制”)
maxsize缓冲区最大大小(以字节为单位)Long0(表示“无最大大小”)

JFR.check:该命令检查正在运行的 JFR 记录。下表列出了可用于此命令的参数。下表描述了可用于该命令的参数。

参数描述值类型默认
name记录名称String-
recording记录 IDLong1
verbose打印详细数据BooleanFalse

JFR.stop:该命令停止正在运行的飞行记录。下表描述了可用于该命令的参数。

参数描述值类型默认
name记录名称String-
recording记录 IDLong1
discard 丢弃记录数据Boolean-
copy_to_file将记录数据复制到文件String-
compress_copyGZip 压缩“copy_to_file”目标BooleanFalse

JFR.dump:该命令将飞行记录信息复制到文件。下表描述了可用于该命令的参数。

参数描述值类型默认
name记录名称String-
recording记录 IDLong1
copy_to_file将记录数据复制到文件String-
compress_copyGZip 压缩“copy_to_file”目标BooleanFalse

记录会话

记录会话指定要收集的确切信息。有两种预配置设置:

  • default:它在最大限度地降低开销的同时提供大量信息。
  • profile:它提供比 default 更多的信息。

我们也可以在Mission Control中配置自己的设置。为了使用 JFR,我们需要激活它。我们可以在 Java 应用程序启动时或运行时激活它。JFR 提供两种记录会话的方法。

  • 使用启动标志
  • 使用 JCMD 工具

使用启动标志

如果我们想在启动时进行连续记录,则使用以下命令:

在上面的命令中,settings 参数接受模板的路径或名称。模板存储在jre\lib\jfr文件夹中。如果想获取更多信息,请更改日志级别,如下所示:

使用 JCMD 工具

如果通过命令行控制 JFR,则使用此命令。

启动记录

检查记录

转储记录

解锁商业功能

我们也可以在退出 JVM 时创建记录。我们需要使用以下选项启动应用程序:

记录也可以通过触发器进行。触发器是在满足指定条件时执行的一组规则。如果要使用触发器创建记录,请在 JMX 控制台中显示的 Triggers 选项卡上定义触发器。

JFR 会定期在记录中创建检查点。它包含事件、常量池事件元数据。它可以在.jfr文件中找到。

记录类型

JFR 允许我们记录两种类型的记录:

  • 固定时间记录
  • 连续记录

固定时间记录

在固定时间记录中,事件会记录固定的一段时间。之后,它会将记录转储到文件中。通常,它用于在指定时间内对 Java 应用程序进行性能分析。

连续记录

在连续记录中,事件没有固定时间。由于记录持续运行。如果我们想停止记录,需要显式转储记录。因此,当我们执行 dump 选项时,我们将获得缓冲区中可用的最近捕获的数据。

下载并安装 JMC

如果您想使用 JFR,则需要安装 JMC。如果您使用的是Eclipse IDE,可以从帮助菜单下的Eclipse Marketplace下载。

让我们通过以下步骤显式下载并安装 JMC:

步骤 1:访问下载 JMC 的链接。该链接会将您带到以下页面。根据您的操作系统,点击链接并下载 JMC。在这里,我们下载 Windows 版 JMC。它开始下载jmc-7.1.2_windows-x64.zip文件。

Java Flight Recorder

步骤 2:解压缩 zip 文件并访问jmc-7.1.2_windows-x64\bin目录。我们会看到以下文件和文件夹列表。

Java Flight Recorder

步骤 3:打开命令提示符并执行jmc命令。

Java Flight Recorder

步骤 4:它会显示一个 Windows 安全警报,请点击允许访问按钮。

Java Flight Recorder

之后,JMC 开始运行。

Java Flight Recorder

以下 JMC 窗口确保 JMC 正在成功运行。

Java Flight Recorder

JFR 实战

让我们创建一个 Java 程序并在实时中监控该程序。以下程序对随机整数序列进行排序。

Main.java

运行程序后,当我们按键时,程序开始工作,因为我们希望程序仅在 Flight Recording 处于活动状态时执行。为了使用 Flight Recorder 执行代码,需要启动 JFR。所以,我们首先编译上面的程序。

Java Flight Recorder

启动 JFR

在应用程序运行之前,请确保它已被分析。运行应用程序有一种特殊的方式。我们将使用以下命令运行应用程序:

在上面的命令中,我们已经解锁了其商业功能,如上所述。之后,我们写了类名,即Main。在类名旁边,10000表示数组的长度。我们传递的另一个参数是 mode,即sorted。它表示 10000 个元素将以什么模式插入数组。让我们运行应用程序。

Java Flight Recorder

现在应用程序正在执行。但正在等待按键。请注意,此时我们不会按任何键,因为 Flight Recorder 尚未启动,并且进程 ID也不知道。所以,在运行程序之前,请确保您拥有进程 ID 并且 JFR 正在运行。

为了知道进程 ID,还有一个名为jps的命令。打开另一个命令提示符并键入命令。

Java Flight Recorder

我们看到它显示了正在运行的应用程序的进程 ID。请注意,每次运行应用程序时,都会获得一个新的进程 ID。

现在,我们将为进程 ID8068运行 Flight Recorder。为了运行录制器,我们使用以下命令:

在上面的命令中,记录名称是my_recording,记录后我们将获得的文件的名称是sorted.jfr。它记录监控 120 秒。

Java Flight Recorder

现在让我们启动Java Mission Control。在命令提示符中,键入start命令,该命令会打开一个新的提示窗口。

Java Flight Recorder

在新提示窗口中,执行命令jmc,该命令会打开 Oracle Java Mission Control。

Java Flight Recorder

现在我们可以开始录制了。JMC 窗口的左窗格中可以看到具有进程 ID 的应用程序,如下所示。

Java Flight Recorder

可视化 JFR 数据

现在我们可以通过访问 JMC 中的.jfr文件来可视化数据。或者,我们可以将应用程序拖放到 JMC 中以查看 Java 应用程序的统计信息。以下窗口代表了应用程序的概览。

Java Flight Recorder

现在我们可以看到实时数据。如果我们仔细查看 Processor 统计信息,我们会发现它每 6 秒记录一次应用程序数据。

Java Flight Recorder

您可以相应地设置时间戳。同样,内存使用量也每 6 秒记录一次。

Java Flight Recorder

它还提供有关 Memory Pool 的信息。在其中,我们可以分析 ClassLoading、Memory、Operating System、Threading、Compilation 等。

Java Flight Recorder

以下快照代表了与线程相关的信息,如线程数、线程连接监控、当前线程 CPU 时间等。

Java Flight Recorder

系统相关信息包括连接、操作系统、操作系统架构、VM 版本等。

Java Flight Recorder

垃圾收集器的详细描述。它包括收集时间、GC 开始时间、GC 结束时间、GC 持续时间、GC ID 等。

Java Flight Recorder

Memory pool 包括堆的详细描述,如 Code Cache、Metaspace、Eden Space、Old Gen 等。

Java Flight Recorder

JFR 中有很多东西可以探索。在此处解释所有内容非常困难。因此,我们建议您自己尝试。

这里需要注意一点。记录尚未开始。要开始记录,请右键单击Flight Recorder,然后单击Start Flight Recording选项,如下图所示。

Java Flight Recorder

它会打开 Flight Recording 对话框。在此对话框中,我们可以设置与记录相关的参数。例如,我们可以设置记录时间。此处,我们指定了 1 分钟的录制。单击Finish按钮后,录制即开始。在右下角,我们可以看到录制的进度。

Java Flight Recorder
Java Flight Recorder

录制完成后,它已经在 JMC 中打开,如下图所示。

Java Flight Recorder

注意:在录制过程中,请勿关闭任何应用程序(如命令提示符、应用程序、Eclipse 等),否则您将获得损坏的 .jfr 文件。生成的 JFR 用于分析应用程序。因此,如果在录制过程中关闭或中断应用程序,这是一种不好的做法。我们还可以过滤和排序数据以进行分析。