JDK Flight Recorder (JFR) 与 Native Image

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

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

JFR 支持默认禁用,必须在构建时明确启用。

注意:在 Windows 上的 Native Image 中,JFR 事件记录尚不可用。

要使用 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 用于标识记录的名称,例如 name=MyRecording
settings 设置文件 (profile.jfc, default.jfc 等),例如 settings=myprofile.jfc
delay 延迟记录开始时间(秒 (s)、分钟 (m)、小时 (h) 或天 (d)),例如 delay=5h
duration 无限 (0) 记录持续时间(秒 (s)、分钟 (m)、小时 (h) 或天 (d)),例如 duration=300s
filename 结果记录文件名,例如 filename=recording1.jfr
maxage 无限制 (0) 磁盘上保留记录数据的最长时间(秒 (s)、分钟 (m)、小时 (h) 或天 (d)),例如 60m,或 0 表示无限制。例如 maxage=1d
maxsize 无限制 (0) 磁盘上保留的最大字节数(KB (k)、MB (M) 或 GB (G)),例如 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 记录。
  • 此选项不区分大小写。

特性与限制 #

本节概述了 Native Image 中可用的 JFR 特性。

方法分析和堆栈跟踪 #

JFR 中的方法分析支持两种采样类型:安全点采样和异步采样。异步采样默认启用,而安全点采样仅在需要时使用。异步采样的优点是避免了安全点偏差,这种偏差发生在分析器不能以相同概率对应用程序中的所有点进行采样时。在这种情况下,采样器只能在安全点进行采样,从而在分析中引入偏差。

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

JFR 事件流 #

JFR 事件流 在 Native Image 中可用。事件流使您能够在应用程序级别注册特定事件的回调。这为记录的管理引入了更大的灵活性和控制。例如,如果事件在流中出现的次数超过一定数量,您可以动态增加事件的持续时间阈值。事件流还使应用程序能够获得连续的定期 JFR 更新,这对于监控目的非常有用。

目前,堆栈跟踪尚未在流式事件中可用。这意味着您无法在其回调方法中访问事件的堆栈跟踪。然而,此限制不影响 JFR 快照文件 (.jfr) 中的堆栈跟踪,它们仍将正常工作。

通过远程 JMX 与 FlightRecorderMXBean 交互 #

您可以通过远程 JMX 连接到 FlightRecorderMXBean,在进程外与 Native Image JFR 交互。这可以使用 JDK Mission Control 或 VisualVM 等应用程序完成。通过 JMX,您可以使用 FlightRecorderMXBean API 作为接口来启动、停止和转储 JFR 记录。

注意:远程 JMX 连接支持需要在构建时单独启用,并且是实验性的。

FlightRecorderOptions #

您可以在运行时使用 -XX:FlightRecorderOptions 微调 JFR 参数。这主要是针对高级用户,大多数人使用默认参数即可。

内存泄漏分析 #

使用 jdk.OldObjectSample 事件实现的内存泄漏分析部分可用。具体来说,可以跟踪旧对象,但无法获取到 GC 根信息的路径。

使用 JFR 和 JCMD #

JFR 可以使用 Java 诊断命令工具 (jcmd) 控制。要启用此功能,必须在构建时配置 jcmd 支持。以下 JFR 命令可与 jcmd 一起使用:JFR.startJFR.stopJFR.checkJFR.dump

内置事件 #

许多 VM 级别的内置事件在 Native Image 中可用。在 HotSpot JVM 上通过字节码插桩实现的 Java 级别事件(例如文件 I/O 和异常内置事件)在 Native Image 中尚不可用。

下表列出了可以使用 Native Image 收集的 JFR 事件。某些事件仅在使用 Serial GC 时可用,Serial GC 是 Native Image 中的默认垃圾收集器。

事件名称
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.NativeMemoryUsage 3)
jdk.NativeMemoryUsageTotal 3)
jdk.NativeMemoryUsagePeak 3)
jdk.NativeMemoryUsageTotalPeak 3)
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) 如果使用 Serial GC,则可用。

2) 如果使用 Serial GC,则部分可用。

3) 如果使用 Native Memory Tracking,则可用。

进一步阅读 #

联系我们