自定义 JDK 飞行记录器事件 - 一口 Java
Billy Korando 于 2022 年 4 月 25 日发布
JDK 飞行记录器 (JFR) 是一款基于事件的分析工具,内置于 JDK 中。在默认设置下,JFR 的开销小于 1%,可用于在生产中跟踪 Java 运行时和应用程序的行为和性能,这对于解决生产错误或寻找性能优化机会很有用。
截至 JDK 18,已有 150 多种预定义的 JFR 事件类型,涵盖了诸如线程创建和删除、GC 暂停、内存分配等事件。这些事件提供了对 Java 运行时和应用程序操作的丰富而详细的视图。但是,在某些情况下,收集的数据可能存在空白,为此,JFR 还支持跟踪自定义事件类型。
创建和使用自定义 JFR 事件
要创建自定义 JFR 事件,请扩展 jdk.jfr.Event
类,如下例所示
import jdk.jfr.Event;
public class MyEvent extends Event {
}
要在应用程序中使用此事件,您需要初始化该事件,然后在要跟踪的代码周围调用 .being()
和 .commit()
,如下所示
public void myMethod(){
MyEvent myEvent = new MyEvent();
myEvent.begin();
//...do work here
myEvent.commit();
}
目前捕获的唯一信息是 .begin()
和 .commit()
之间的执行时间和堆栈。但是,自定义事件可以捕获其他信息。
允许的 JFR 字段
允许自定义 JFR 事件具有 JFR 将收集的字段,但这些字段必须属于以下类型
- byte
- short
- int
- long
- float
- double
- char
- boolean
- java.lang.String,可以为 null
- java.lang.Thread,可以为 null
- java.lang.Class,可以为 null
这些字段可以为应用程序中发生的情况提供其他上下文,例如,客户端输入的值、从其他系统返回的值或开发人员可能发现有用的其他信息。JFR 将静默忽略上述类型之外的字段。
JFR 注释
JFR 还提供注释来控制事件何时启用,或提供元数据。需要注意的关键注释包括
- 类别:事件注释,以人类可读路径的格式将事件类型与类别关联。
- 描述:使用一两句话描述元素的注释。
- 已启用:事件注释,确定是否应默认启用事件。
- 标签:为元素设置人类可读名称的注释(例如,“最大吞吐量”)。
- 名称:设置元素默认名称的注释。
- StackTrace:事件注释,确定事件默认情况下是否具有堆栈跟踪。
- Threshold:事件注释,指定事件未记录的默认持续时间(例如,“20 毫秒”)。
其他注释
JFR 还预定义了其他一些注释
- BooleanFlag:事件字段注释,指定该值是一个布尔标志,一个真或假值。
- ContentType:元注释,指定注释表示内容类型,例如时间跨度或频率。
- DataAmount:事件字段注释,指定值表示数据量(例如,字节)。
- Experimental:指定元素是实验性的,可能会在不通知的情况下更改的注释。
- Frequency:事件字段注释,指定该值是一个频率,以赫兹为单位测量。
- MemoryAddress:事件字段注释,指定该值是一个内存地址。
- MetadataDefinition:用于定义新类型的事件元数据的元注释。
- Percentage:用于分数的事件字段注释,通常介于 0.0 和 1.0 之间,以指定该值是一个百分比。
- Period:事件注释,指定周期性事件的默认设置值。
- Registered:事件注释,用于编程事件注册。
- Relational:用于关系注释的元注释,用于注释。
- SettingDefinition:指定事件类中的方法应用于过滤事件的注释。
- Timespan:事件字段注释,指定该值是一个持续时间。
- Timestamp:事件字段注释,指定该值是一个时间点。
- TransitionFrom:事件字段注释,指定事件从线程转换而来。
- TransitionTo:事件字段注释,指定事件将很快转换到线程。
- Unsigned:事件字段注释,指定该值是一个无符号数据类型。
配置 JFR 事件
预定义事件和自定义事件都可以使用 .jfc
文件或通过命令行进行配置。在 .jfc
文件中配置事件将如下所示
<configuration>
...
<event name="com.oracle.jfr.MyEvent">
<setting name="enabled">true</setting>
</event>
...
</configuration>
注意:如果未使用 @Name
标记,则事件的默认名称将是其完全限定名称。
事件也可以通过命令行进行配置,如下面的示例所示
-XX:StartFlightRecording=event-setting=<event-name>#<setting-name>=<value>
进一步阅读
有关 JDK Flight Recorder、其 API 或在应用程序中使用 JDK Flight Recorder 的更多信息,请务必查看以下链接
- Flight Recorder API 程序员指南
- Java 的高级运行时选项
- 使用 JDK Flight Recorder 进行持续监控 [视频]
- “JDK Flight Recorder” [播客]
编码愉快!