使用原生映像的 JDK Flight Recorder (JFR)

JDK Flight Recorder (JFR) 是一个事件记录器,用于捕获有关 JVM 以及在 JVM 上运行的应用程序的信息。GraalVM 原生映像支持构建包含 JFR 事件的原生可执行文件,用户可以使用 jdk.jfr.Event API,体验与在 Java HotSpot VM 中使用 JFR 相似的体验。

在构建时包含 JFR 支持,并在运行时记录事件 #

默认情况下,JFR 支持处于禁用状态,必须在构建时显式启用。

注意:JFR 事件记录在 Windows 上的 GraalVM JDK 中尚不可用。

若要构建包含 JFR 的原生可执行文件,请使用 --enable-monitoring=jfr 选项

native-image --enable-monitoring=jfr JavaApplication

以下选项支持在运行时启动记录和配置日志记录

  • -XX:StartFlightRecording:在应用程序启动时启动记录
  • -XX:FlightRecorderLogging:配置 JFR 的日志输出

若要启动 JFR 记录,只需在运行时使用 -XX:StartFlightRecording。例如

./javaapplication -XX:StartFlightRecording="filename=recording.jfr"

配置 JFR 记录 #

与在 HotSpot 上启动 JFR 记录的方式类似,您可以通过将逗号分隔的键值对列表传递给 -XX:StartFlightRecording 选项来启动记录。例如

-XX:StartFlightRecording="filename=recording.jfr,dumponexit=true,duration=10s"

支持以下键值对

名称 默认值 描述
name none 用于标识记录的名称,例如 name=MyRecording
settings none 设置文件(profile.jfcdefault.jfc 等),例如 settings=myprofile.jfc
delay none 以 (s) 秒、(m) 分钟、(h) 小时或 (d) 天延迟记录启动,例如 delay=5h
duration infinite (0) 以 (s) 秒、(m) 分钟、(h) 小时或 (d) 天记录持续时间,例如 duration=300s
filename none 生成的记录文件名,例如 filename=recording1.jfr
maxage no limit (0) 在磁盘上保留记录数据的最长时间,以 (s) 秒、(m) 分钟、(h) 小时或 (d) 天为单位,例如 60m,或 0 表示无限制。例如 maxage=1d
maxsize no limit (0) 在磁盘上保留的最大字节数,以 (k)B、(M)B 或 (G)B 为单位,例如 500M,或 0 表示无限制。例如 maxsize=1G
dumponexit false 是否在 JVM 关闭时转储正在运行的记录,例如 dumponexit=true

配置 JFR 系统日志记录 #

您可以使用单独的标志 -XX:FlightRecorderLogging 配置 JFR 系统的日志记录。用法如下:-XX:FlightRecorderLogging=[tag1[+tag2...][*][=level][,...]]。例如

-XX:FlightRecorderLogging=jfr,system=debug
-XX:FlightRecorderLogging=all=trace
-XX:FlightRecorderLogging=jfr*=error
  • 如果未设置此选项,则日志记录将在 WARNING 级别启用。
  • 如果将此选项设置为空字符串,则日志记录将在 INFO 级别启用。
  • 如果将此选项设置为“disable”,则完全禁用日志记录。

可用的日志级别为:trace, debug, info, warning, error, off

可用的日志标签为:all, jfr, system, event, setting, bytecode, parser, metadata, dcmd

否则,此选项将期望一个逗号分隔的标签组合列表,每个组合可以选择包含通配符 (*) 和级别。

  • 没有级别的标签组合将被赋予默认级别 INFO
  • 如果消息的标签与给定的标签组合匹配,则将记录这些消息,前提是它们满足标签组合的级别。
  • 如果标签组合没有通配符,则仅匹配标签完全相同的消息。否则,将匹配标签是标签组合的子集的消息。
  • 如果多个标签组合匹配消息的标签,则最右边的组合将适用。
  • 标签没有匹配的标签组合的消息将被设置为在 WARNING 默认级别进行日志记录。
  • 此选项不区分大小写。

功能和局限性 #

本节概述了原生映像中可用的 JFR 功能。

方法分析和堆栈跟踪 #

JFR 中的方法分析支持两种类型的采样:安全点采样和异步采样。异步采样默认情况下处于启用状态,而安全点采样仅在需要时使用。异步采样具有避免安全点偏差的优势,安全点偏差是指如果分析器没有以相等的概率对应用程序中的所有点进行采样,就会发生这种情况。在这种情况下,采样器只能在安全点执行采样,从而在分析中引入偏差。

两种采样器都会定期以指定频率生成事件 jdk.ExecutionSample。这些样本可以在 JDK Mission Control 或 VisualVM 等应用程序中查看。此外,支持 HotSpot 上堆栈跟踪的其他 JFR 事件也支持原生映像中的堆栈跟踪。这意味着您可以执行一些有趣的操作,例如查看 jdk.ObjectAllocationInNewTLAB 的火焰图,以诊断对象分配经常发生的位置。

JFR 事件流 #

JFR 事件流 在原生映像中可用。事件流使您能够在应用程序级别为特定事件注册回调。这为管理记录方式带来了更大的灵活性,并提供了更多的控制。例如,如果发现事件流中的某个事件超过了一定次数,您可以动态地增加其持续时间阈值。事件流还使应用程序能够获得持续的定期 JFR 更新,这些更新对于监控目的很有用。

目前,堆栈跟踪在流式事件中尚不可用。这意味着您无法在回调方法内部访问事件的堆栈跟踪。但是,此限制不会影响 JFR 快照文件 (.jfr) 中的堆栈跟踪,这些堆栈跟踪将照常工作。

通过远程 JMX 与 FlightRecorderMXBean 交互 #

您可以通过远程 JMX 连接到 FlightRecorderMXBean 从进程外部与原生映像 JFR 交互。可以使用 JDK Mission Control 或 VisualVM 等应用程序执行此操作。通过 JMX,您可以使用 FlightRecorderMXBean API 作为接口,启动、停止和转储 JFR 记录。

注意:远程 JMX 连接支持需要在构建时单独启用,并且处于实验阶段。

FlightRecorderOptions #

您可以通过在运行时使用 -XX:FlightRecorderOptions 来微调 JFR 参数。这主要用于高级用户,大多数用户应该可以使用默认参数。

泄漏分析 #

使用 jdk.OldObjectSample 事件实现的泄漏分析部分可用。具体来说,旧对象跟踪是可能的,但到 GC 根的信息路径不可用。

内置事件 #

原生映像中提供了许多 VM 级别的内置事件。通过 HotSpot JVM 上的字节码检测实现的 Java 级别的事件在原生映像中尚不可用。这些事件包括文件 I/O 和异常内置事件。

下表列出了可以使用原生映像收集的 JFR 事件。某些事件仅在使用 串行 GC(原生映像中的默认垃圾收集器)时可用。

事件名称
jdk.ActiveRecording
jdk.ActiveSetting
jdk.AllocationRequiringGC 1)
jdk.ClassLoadingStatistics
jdk.ContainerCPUThrottling
jdk.ContainerCPUUsage
jdk.ContainerConfiguration
jdk.ContainerIOUsage
jdk.ContainerMemoryUsage
jdk.DataLoss
jdk.ExecutionSample
jdk.ExecuteVMOperation
jdk.GarbageCollection 1)
jdk.GCHeapSummary 1)
jdk.GCPhasePause 1)
jdk.GCPhasePauseLevel1 1)
jdk.GCPhasePauseLevel2 1)
jdk.GCPhasePauseLevel3 1)
jdk.GCPhasePauseLevel4 1)
jdk.InitialEnvironmentVariable
jdk.InitialSystemProperty
jdk.JavaMonitorEnter
jdk.JavaMonitorInflate
jdk.JavaMonitorWait
jdk.JavaThreadStatistics
jdk.JVMInformation
jdk.ObjectAllocationSample 1)
jdk.ObjectAllocationInNewTLAB 1)
jdk.OldObjectSample 2)
jdk.OSInformation
jdk.PhysicalMemory
jdk.SafepointBegin
jdk.SafepointEnd
jdk.SocketRead
jdk.SocketWrite
jdk.SystemGC 1)
jdk.ThreadAllocationStatistics
jdk.ThreadCPULoad
jdk.ThreadEnd
jdk.ThreadPark
jdk.ThreadSleep
jdk.ThreadStart
jdk.VirtualThreadEnd
jdk.VirtualThreadPinned
jdk.VirtualThreadStart

1) 使用串行 GC 时可用。

2) 使用串行 GC 时部分可用。

进一步阅读 #

与我们联系