JFR 事件流 - Sip of Java
Billy Korando 于 2022 年 5 月 12 日
JDK Flight Recorder (JFR) 是一种基于事件的工具,用于监控和分析 JDK 中内置的性能。JFR 在使用默认设置时具有非常低的开销(<1%),使其可以在生产环境中使用。通常,从 JFR 中提取信息需要执行转储;但是,在 JDK 14 中添加了 jdk.jfr.consumer
包,该包提供了用于使用 JFR 事件的 API,而无需执行 JFR 转储。让我们看看如何使用此 API。
创建 JFR 事件流
新事件流 API 中的核心类是接口 jdk.jfr.consumer.EventStream
,顾名思义,它表示事件流。
EventStream 工厂方法
EventStream
提供了三种工厂方法来创建新的 EventStream
实例
openFile(java.nio.file.Path)
- 从录制文件创建EventStream
。openRepository()
- 从当前 JVM 的存储库创建EventStream
。openRepository(java.nio.file.Path)
- 从目录创建EventStream
。
EventStream 实现
还有两个可以实例化的公共实现
jdk.jfr.consumer.RecordingStream
- 当前 JVM 的录制流。jdk.management.jfr.RemoteRecordingStream
- 可以使用javax.management.MBeanServerConnection
序列化事件的录制流
注册事件
创建 EventStream
后,可以向其注册操作。有两种方法可以为事件注册操作
-
onEvent(consumer)
- 所有事件都将注册到此操作。 -
onEvent(String, Consumer)
- 只有名称匹配的事件才会注册到此操作。
此外,还可以为满足其他条件时注册操作
onClose(Runnable)
- 注册在流关闭时执行的操作。onError(Consumer<Throwable>)
- 注册在发生异常时执行的操作。onFlush(Runnable)
- 注册在流刷新后执行的操作。onMetadata(Consumer<MetadataEvent>)
- 注册在流中收到新元数据时执行的操作。示例
创建 JFR 事件流的示例可能如下所示。在此示例中,流检查何时监控的进程从文件读取并打印事件的开始时间、结束时间和总持续时间到控制台。
try (EventStream es = EventStream.openRepository()) {
es.onEvent("jdk.FileRead", event -> {
System.out.println("File read!");
System.out.println("Start: " + event.getStartTime());
System.out.println("End: " + event.getEndTime());
System.out.println("Duration: " + event.getDuration());
});
es.start();
}
附加流
JFR 事件流可以作为进程内和外部进程附加。JFR 事件流如何附加到外部进程的示例包括
- Java 代理
- 进程 ID
- JMX 套接字
- 从录制文件读取
- 等等!
JFR 事件流性能开销
虽然 JFR 在使用默认设置时目标开销 <1%,但 JFR 事件流的实现方式会影响性能。注册到流中的事件数量和操作的行为将决定进程内流的性能影响。
对于外部流,如何检索事件可能会影响性能。如果事件通过 JMX 套接字流式传输,则需要序列化流事件,这可能意味着巨大的开销。但是,如果外部流从录制文件或目录读取,则不会对监控进程造成任何额外的开销。
其他阅读材料
编码愉快!