Java Flight Recorder2025年5月3日 | 阅读 14 分钟 Java Flight Recorder (JFR) 是一种强大的性能监控和分析工具。它可以在持续的基础上诊断、收集和监控正在运行的 Java 应用程序,即使在发生灾难性故障时也能如此。它集成在 JVM 中。该工具提供了一个强大的 GUI 来进行应用程序性能分析。它被用于高负载的生产环境应用程序,如性能分析、黑盒分析支持和调试。在本节中,我们将详细讨论Java Flight Recorder。此外,我们还将了解它的概念、用途、架构、JMC和JFR的基本命令。 什么是 Java Flight Recorder (JFR)?它首次引入于JDK 1.7。它的功能是用Java编写的。它是一种应用程序诊断工具,可以捕获JVM和应用程序数据。这些数据包括垃圾回收、同步、编译器、CPU使用率、异常、I/O 等。它还提供了一个基于采样的分析器。借助分析器,我们可以获得准确的数据和低开销。它使用循环缓冲区来存储数据。 ![]() 上图描绘了循环飞行记录缓冲区的概念。新数据不断添加到缓冲区,旧数据被移除。 JFR 工具不能独立使用。因此,它与 Java Mission Control (JMC) 一起使用。JMC 工具包含一个插件,允许我们可视化 JFR 收集的数据。除了 JFR,JDK 还提供了一些其他工具用于监控和分析。
请注意,Java VisualVM 过去是 Oracle 和 Open JDK 发行版的一部分。自 Java 9 起,Java VisualVM 已被移除。下图描绘了 JFR 的演变。 ![]() 注意:如果要在生产环境中使用 JFR 工具,需要商业许可证。Java Flight Recorder 的优点与 JFR 类似,也有一些其他工具可用。但 JFR 相较于它们有一些优势,如下所示:
Flight Recorder 的用途
JFR 架构JFR 架构包含以下内容: JFR 包含一个生成记录的运行时引擎。运行时引擎有两个组件:Agent 和 Producers。 Agent 的工作是处理缓冲区、磁盘和 MBeans 等。它提供了一个用 C 和 Java 代码编写的动态库。Producers 将数据写入缓冲区。 JFR 插件使我们能够使用 JMC。我们可以通过 GUI 轻松地启动、停止和配置记录。 ![]() JFR 组件JFR 有两个主要概念:Event 和 Dataflow。让我们简要讨论一下。 JFR 事件在 JFR 中,一切都是一个事件。它收集 JVM 中发生的事件以及应用程序日志。事件代表 JVM 和应用程序的状态。JFR 收集的信息分为两部分:Header 和 Payload。 ![]() Header 包括大小、事件 ID 和结束时间。Payload 包含特定于事件的数据。除此之外,它还包括开始时间、线程 ID 和堆栈跟踪 ID,但这些是可选的 Payload。记录事件时,必须定义以下两项:
Content-Type 描述了值的语义。它在 UI 中正确表示值。
因此,事件收集了应用程序的非常高层级的数据。我们应该始终记录实际需要的事件,因为这可以最大限度地减少开销。我们还可以按类型、名称和持续时间过滤事件。 事件类型JFR 收集以下三种类型的事件: ![]()
创建事件 我们可以使用以下代码片段创建自己的事件。 让我们为一些常量创建一个事件。 在上面的代码中,我们还可以做一些额外的事情,为应用程序提供一些有用的提示。为此,我们使用注解。 JFR 注解 下表列出了一些有用的注解。还有一些其他注解可以在Javadoc中找到。
JFR 数据流事件批量从 JVM 和 Java 应用程序收集数据。它从两者收集数据并将其存储在小的线程本地缓冲区中。然后,当线程缓冲区达到极限时,数据会被刷新到全局缓冲区(或内存中)。类似地,当全局缓冲区达到极限时,旧数据将被丢弃。之后,数据被刷新到存储库。 ![]() 因此,它的设计足够快,不会抑制程序。所有事件的数据都存储在flight.jfr文件中,因为磁盘 I/O 操作成本更高。该机制更复杂,因为同时应用程序可能具有多个具有不同选项的注册进程。 注意:不可能在两个地方获取数据。这意味着数据块将在磁盘或内存(缓冲区)中可用,但不会同时存在。这避免了数据重叠。因此,使用 JFR,我们在 JFR 文件中获得的平均数据比请求的要多。请记住,数据可能按时间顺序排列,也可能不按时间顺序排列。下图描绘了 JFR 中事件的数据流。 运行 Java Flight Recorder配置 JFR在启用 JFR 工具之前,请确保您使用的是同一 JDK 发行版中的 javac、java、JFR、JMC 和 jcmd 工具。如果您安装了不同版本的 Java,它可能会提供错误的数据。 启用 JFR我们知道这是一个商业功能。因此,在运行它之前,我们需要解锁商业功能。可以使用以下标志来解锁: 其中DemoApp是应用程序名称。 注意:如果您使用的是 Java 11,则无需激活其商业功能。启动 JFR或 高级配置
有三种运行 JFR 的方法:
使用 JMC 中的 JFR 插件我们可以使用 JFR 插件创建记录。它已集成到 JMC 中。请按照以下步骤创建记录:
使用命令行选项当我们在启动应用程序时使用 java 命令,我们也可以启用 JFR、配置它并开始记录。
注意:命令行选项在 JDK 的商业许可证中可用。如果您想使用它,需要使用以下选项启用它:使用诊断命令以下四个诊断命令与 JFR 相关:
JFR.start:该命令启动飞行记录。下表描述了可用于该命令的参数。
JFR.check:该命令检查正在运行的 JFR 记录。下表列出了可用于此命令的参数。下表描述了可用于该命令的参数。
JFR.stop:该命令停止正在运行的飞行记录。下表描述了可用于该命令的参数。
JFR.dump:该命令将飞行记录信息复制到文件。下表描述了可用于该命令的参数。
记录会话记录会话指定要收集的确切信息。有两种预配置设置:
我们也可以在Mission Control中配置自己的设置。为了使用 JFR,我们需要激活它。我们可以在 Java 应用程序启动时或运行时激活它。JFR 提供两种记录会话的方法。
使用启动标志如果我们想在启动时进行连续记录,则使用以下命令: 在上面的命令中,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文件。 ![]() 步骤 2:解压缩 zip 文件并访问jmc-7.1.2_windows-x64\bin目录。我们会看到以下文件和文件夹列表。 ![]() 步骤 3:打开命令提示符并执行jmc命令。 ![]() 步骤 4:它会显示一个 Windows 安全警报,请点击允许访问按钮。 ![]() 之后,JMC 开始运行。 ![]() 以下 JMC 窗口确保 JMC 正在成功运行。 ![]() JFR 实战让我们创建一个 Java 程序并在实时中监控该程序。以下程序对随机整数序列进行排序。 Main.java 运行程序后,当我们按键时,程序开始工作,因为我们希望程序仅在 Flight Recording 处于活动状态时执行。为了使用 Flight Recorder 执行代码,需要启动 JFR。所以,我们首先编译上面的程序。 ![]() 启动 JFR在应用程序运行之前,请确保它已被分析。运行应用程序有一种特殊的方式。我们将使用以下命令运行应用程序: 在上面的命令中,我们已经解锁了其商业功能,如上所述。之后,我们写了类名,即Main。在类名旁边,10000表示数组的长度。我们传递的另一个参数是 mode,即sorted。它表示 10000 个元素将以什么模式插入数组。让我们运行应用程序。 ![]() 现在应用程序正在执行。但正在等待按键。请注意,此时我们不会按任何键,因为 Flight Recorder 尚未启动,并且进程 ID也不知道。所以,在运行程序之前,请确保您拥有进程 ID 并且 JFR 正在运行。 为了知道进程 ID,还有一个名为jps的命令。打开另一个命令提示符并键入命令。 ![]() 我们看到它显示了正在运行的应用程序的进程 ID。请注意,每次运行应用程序时,都会获得一个新的进程 ID。 现在,我们将为进程 ID8068运行 Flight Recorder。为了运行录制器,我们使用以下命令: 在上面的命令中,记录名称是my_recording,记录后我们将获得的文件的名称是sorted.jfr。它记录监控 120 秒。 ![]() 现在让我们启动Java Mission Control。在命令提示符中,键入start命令,该命令会打开一个新的提示窗口。 ![]() 在新提示窗口中,执行命令jmc,该命令会打开 Oracle Java Mission Control。 ![]() 现在我们可以开始录制了。JMC 窗口的左窗格中可以看到具有进程 ID 的应用程序,如下所示。 ![]() 可视化 JFR 数据现在我们可以通过访问 JMC 中的.jfr文件来可视化数据。或者,我们可以将应用程序拖放到 JMC 中以查看 Java 应用程序的统计信息。以下窗口代表了应用程序的概览。 ![]() 现在我们可以看到实时数据。如果我们仔细查看 Processor 统计信息,我们会发现它每 6 秒记录一次应用程序数据。 ![]() 您可以相应地设置时间戳。同样,内存使用量也每 6 秒记录一次。 ![]() 它还提供有关 Memory Pool 的信息。在其中,我们可以分析 ClassLoading、Memory、Operating System、Threading、Compilation 等。 ![]() 以下快照代表了与线程相关的信息,如线程数、线程连接监控、当前线程 CPU 时间等。 ![]() 系统相关信息包括连接、操作系统、操作系统架构、VM 版本等。 ![]() 垃圾收集器的详细描述。它包括收集时间、GC 开始时间、GC 结束时间、GC 持续时间、GC ID 等。 ![]() Memory pool 包括堆的详细描述,如 Code Cache、Metaspace、Eden Space、Old Gen 等。 ![]() JFR 中有很多东西可以探索。在此处解释所有内容非常困难。因此,我们建议您自己尝试。 这里需要注意一点。记录尚未开始。要开始记录,请右键单击Flight Recorder,然后单击Start Flight Recording选项,如下图所示。 ![]() 它会打开 Flight Recording 对话框。在此对话框中,我们可以设置与记录相关的参数。例如,我们可以设置记录时间。此处,我们指定了 1 分钟的录制。单击Finish按钮后,录制即开始。在右下角,我们可以看到录制的进度。 ![]() ![]() 录制完成后,它已经在 JMC 中打开,如下图所示。 ![]() 注意:在录制过程中,请勿关闭任何应用程序(如命令提示符、应用程序、Eclipse 等),否则您将获得损坏的 .jfr 文件。生成的 JFR 用于分析应用程序。因此,如果在录制过程中关闭或中断应用程序,这是一种不好的做法。我们还可以过滤和排序数据以进行分析。下一个主题数组求和问题的索引-Java |
对象克隆表示创建文章的精确副本。它会创建一个正在进行文章的类的另一个实例,并使用正在进行项目中的相应字段中的相同对象初始化其所有字段。使用赋值运算符创建...
阅读 12 分钟
在本节中,我们将创建Java程序,使用具有不同逻辑的函数来交换两个数字。步骤1:开始步骤2:定义x、y、t步骤3:输入x、y步骤4:打印x、y步骤5:t = x步骤6:x = y步骤7:y = t步骤8:打印x,...
阅读 2 分钟
像泛型和通配符这样的基本 Java 功能可以提高像集合这样的数据结构的类型安全性和灵活性。但它们之间略有不同。在本节中,我们将讨论 Java 中泛型和通配符之间的区别。什么是 Java 中的泛型?泛型主要是...
阅读 4 分钟
?在 Java 中,注解是关于源代码的元数据。它们对 Java 程序的执行没有直接影响。Java 中的注解是在 JDK 5 中引入的。使用注解的主要目的是它向编译器提供指令...
阅读 4 分钟
在动态的 Java 开发世界中创建稳定且响应迅速的应用程序需要有效的任务管理。Java 并发可以通过异步编程和多线程来实现。Java 编程中的多线程概念允许在单个程序中同时运行多个线程。编写程序...
5 分钟阅读
在本节中,我们将学习什么是神秘数字,并创建 Java 程序来检查给定数字是否为神秘数字。神秘数字程序经常在 Java 编码测试和学术界中出现。神秘数字 如果一个数字 N 被称为...
阅读 3 分钟
java.text.CollationElementIterator 类有一个 tertiaryOrder() 方法。CollationElementIterator 类的 tertiaryOrder() 方法提供 CollationElementIterator 对象每个排序元素的第三级组件。语法:public static final short tertiaryOrder(int order) 参数:该方法需要发现排序元素的第三级组件,该排序元素是...
阅读 3 分钟
我们收到一个字符串作为输入。任务是确定给定的字符串是否以大写字母开头。示例 1:输入:String s = "Hello World" 输出:这是一个有效字符串。说明:给定的字符串以“H”开头,这是一个大写字母。示例 2:输入:String s...
阅读 3 分钟
Java 中的 Read-Eval-Print Loop (REPL) Read-Eval-Print Loop 或 REPL 是一个 shell 接口。该接口读取并评估每一行输入,然后打印结果。Read-Eval-Print Loop 帮助我们与特定状态下的应用程序运行时进行交互。命令是...
5 分钟阅读
Java 5 中引入的泛型为开发人员编写和使用 Java 集合的方式带来了革命性的变化。泛型允许类和方法对各种类型的对象进行操作,同时提供编译时类型安全。这一强大功能具有许多优点,有助于编写更清晰、更...
阅读 4 分钟
我们请求您订阅我们的新闻通讯以获取最新更新。
我们提供所有技术(如 Java 教程、Android、Java 框架)的教程和面试问题
G-13, 2nd Floor, Sec-3, Noida, UP, 201301, India