JFR 事件流 - Sip of Java

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 套接字流式传输,则需要序列化流事件,这可能意味着巨大的开销。但是,如果外部流从录制文件或目录读取,则不会对监控进程造成任何额外的开销。

其他阅读材料

编码愉快!