- 所有超接口:
-
AutoCloseable
- 所有已知实现类:
-
RecordingStream
,RemoteRecordingStream
流是事件序列,与流交互的方式是注册操作。不应实现EventStream
接口,未来的JDK版本可能会完全禁止这样做。
要在事件到达时接收通知,请使用onEvent(Consumer)
方法注册操作。要过滤具有特定名称的事件流,请使用onEvent(String, Consumer)
方法。
默认情况下,相同的RecordedEvent
对象可用于表示两个或多个不同的事件。该对象可以多次传递给相同的操作,也可以传递给其他操作。要在操作完成后使用事件对象,应将setReuse(boolean)
方法设置为false
,以便为每个事件分配一个新对象。
事件以批次传递。要在批次完成时接收通知,请使用onFlush(Runnable)
方法注册操作。这是一个机会,可以在Java虚拟机(JVM)准备下一批时聚合或将数据推送到外部系统。
批次内的事件按其结束时间按时间顺序排序。事件的良序仅对JVM在刷新点可用的事件保持,即作为单个批次传递的事件集。因此,批次中传递的事件可能与先前批次中传递的事件不一致,但永远不会与同一批次中的事件不一致。如果不关心排序,可以使用setOrdered(boolean)
方法禁用排序。
要将事件分派给已注册的操作,必须启动流。要在当前线程中开始处理,请调用start()
方法。要在单独的线程中异步处理操作,请调用startAsync()
方法。要等待流的完成,请使用awaitTermination()
或awaitTermination(Duration)
方法。
当流结束时,它会自动关闭。要手动停止事件处理,请通过调用close()
方法关闭流。在异常情况下,例如被监视的JVM退出时,流也可以自动关闭。要在任何这些情况下接收通知,请使用onClose(Runnable)
方法注册操作。
如果操作中发生意外异常,可以在错误处理程序中捕获异常。可以使用onError(Consumer)
方法注册错误处理程序。如果未注册错误处理程序,则默认行为是将异常及其回溯打印到标准错误流。
以下示例显示了如何使用EventStream
来监听运行Flight Recorder的JVM上的事件
try (var es = EventStream.openRepository()) {
es.onEvent("jdk.CPULoad", event -> {
System.out.println("CPU Load " + event.getEndTime());
System.out.println(" Machine total: " + 100 * event.getFloat("machineTotal") + "%");
System.out.println(" JVM User: " + 100 * event.getFloat("jvmUser") + "%");
System.out.println(" JVM System: " + 100 * event.getFloat("jvmSystem") + "%");
System.out.println();
});
es.onEvent("jdk.GarbageCollection", event -> {
System.out.println("Garbage collection: " + event.getLong("gcId"));
System.out.println(" Cause: " + event.getString("cause"));
System.out.println(" Total pause: " + event.getDuration("sumOfPauses"));
System.out.println(" Longest pause: " + event.getDuration("longestPause"));
System.out.println();
});
es.start();
}
要与流一起开始记录,请参见RecordingStream
。
- 自 JDK 版本:
- 14
-
Method Summary
Modifier and TypeMethodDescriptionvoid
阻塞,直到所有操作完成,或流关闭,或当前线程被中断,以先发生者为准。void
awaitTermination
(Duration timeout) 阻塞,直到所有操作完成,或流关闭,或超时发生,或当前线程被中断,以先发生者为准。void
close()
释放与此流相关的所有资源。void
注册在流关闭时执行的操作。void
注册在发生异常时执行的操作。void
onEvent
(String eventName, Consumer<RecordedEvent> action) 注册在所有匹配名称的事件上执行的操作。void
onEvent
(Consumer<RecordedEvent> action) 注册在流中所有事件上执行的操作。void
注册在流刷新后执行的操作。default void
onMetadata
(Consumer<MetadataEvent> action) 注册在流中新元数据到达时执行的操作。static EventStream
从文件创建事件流。static EventStream
从当前Java虚拟机(JVM)的存储库创建流。static EventStream
openRepository
(Path directory) 从磁盘存储库创建事件流。boolean
注销操作。void
setEndTime
(Instant endTime) 指定流的结束时间。void
setOrdered
(boolean ordered) 指定事件按照它们提交到流的时间按时间顺序到达的顺序。void
setReuse
(boolean reuse) 指定onEvent(Consumer)
操作中的事件对象可以重用。void
setStartTime
(Instant startTime) 指定流的开始时间。void
start()
开始处理操作。void
开始异步处理操作。
-
Method Details
-
openRepository
从当前Java虚拟机(JVM)的存储库创建流。默认情况下,流从Flight Recorder刷新的下一个事件开始。
- 返回:
-
一个事件流,非
null
- 抛出:
-
IOException
- 如果无法打开流,或在尝试访问存储库时发生I/O错误 -
SecurityException
- 如果存在安全管理器并且调用者没有FlightRecorderPermission("accessFlightRecorder")
-
openRepository
从磁盘存储库创建事件流。默认情况下,流从Flight Recorder刷新的下一个事件开始。
只应打开受信任的磁盘存储库。
- 参数:
-
directory
- 磁盘存储库的位置,非null
- 返回:
-
一个事件流,非
null
- 抛出:
-
IOException
- 如果无法打开流,或在尝试访问存储库时发生I/O错误 -
SecurityException
- 如果存在安全管理器并且其checkRead
方法拒绝对目录或目录中的文件的读取访问
-
openFile
从文件创建事件流。默认情况下,流从文件中的第一个事件开始。
只应打开来自受信任来源的记录文件。
- 参数:
-
file
- 文件的位置,非null
- 返回:
-
一个事件流,非
null
- 抛出:
-
IOException
- 如果无法打开文件,或在读取过程中发生I/O错误 -
SecurityException
- 如果存在安全管理器并且其checkRead
方法拒绝对文件的读取访问
-
onMetadata
注册在流中新元数据到达时执行的操作。事件的事件类型总是在实际事件之前到达。操作必须在流开始之前注册。以下示例显示了如何监听新事件类型,如果事件类型名称与正则表达式匹配,则注册操作,并且如果找到匹配的事件,则增加计数器。使用每个事件类型一个操作,而不是通用的
onEvent(Consumer)
方法的好处是,流实现可以避免读取不感兴趣的事件。static long count = 0; public static void main(String... args) throws IOException { Path file = Path.of(args[0]); String regExp = args[1]; var pr = Pattern.compile(regExp).asMatchPredicate(); try (var s = EventStream.openFile(file)) { s.setOrdered(false); s.onMetadata(metadata -> metadata.getAddedEventTypes() .stream().map(EventType::getName).filter(pr) .forEach(eventName -> s.onEvent(eventName, event -> count++))); s.start(); System.out.println(count + " events matches " + regExp); } }
- 实现要求:
- 此方法的默认实现为空。
- 参数:
-
action
- 要执行的操作,非null
- 抛出:
-
IllegalStateException
- 如果在流开始后添加了操作 - 自 JDK 版本:
- 16
-
onEvent
注册一个在流中的所有事件上执行的操作。要在事件类型的子集上执行操作,请考虑使用
onEvent(String, Consumer)
和onMetadata(Consumer)
,因为这可能比在通用操作中实现的任何选择或过滤机制更高效。- 参数:
-
action
- 在每个RecordedEvent
上执行的操作,不能为空 - 参见:
-
onEvent
注册一个在匹配名称的所有事件上执行的操作。- 参数:
-
eventName
- 事件的名称,不能为空 -
action
- 在匹配事件名称的每个RecordedEvent
上执行的操作,不能为空
-
onFlush
注册一个在流刷新后执行的操作。- 参数:
-
action
- 在流刷新后执行的操作,不能为空
-
onError
注册一个在发生异常时执行的操作。如果未注册操作,则异常堆栈跟踪将打印到标准错误输出。
注册操作会覆盖默认行为。如果已注册多个操作,则按注册顺序执行它们。
如果此方法本身引发异常,则结果行为是未定义的。
- 参数:
-
action
- 在发生异常时执行的操作,不能为空
-
onClose
注册一个在流关闭时执行的操作。如果流已关闭,则操作将立即在当前线程中执行。
- 参数:
-
action
- 在流关闭后执行的操作,不能为空 - 参见:
-
close
void close()释放与此流关联的所有资源。如果流已启动(异步或同步),则立即停止或在下一次刷新后停止。此方法不保证在返回之前完成所有已注册的操作。
关闭先前关闭的流不会产生任何效果。
- 指定者:
-
close
在接口AutoCloseable
-
remove
注销一个操作。如果操作已注册多次,则所有实例都将被注销。
- 参数:
-
action
- 要注销的操作,不能为空 - 返回:
-
true
表示操作已注销,否则为false
- 参见:
-
setReuse
void setReuse(boolean reuse) 指定在onEvent(Consumer)
操作中的事件对象可以被重用。如果重用设置为
true
,则操作完成后不应保留对事件对象的引用。- 参数:
-
reuse
- 如果可以重用事件对象,则为true
,否则为false
-
setOrdered
void setOrdered(boolean ordered) 指定事件按照它们提交到流中的时间按时间顺序到达。- 参数:
-
ordered
- 如果事件对象按时间顺序到达onEvent(Consumer)
-
setStartTime
指定流的开始时间。必须在启动流之前设置开始时间
- 参数:
-
startTime
- 开始时间,不能为空 - 抛出:
-
IllegalStateException
- 如果流已经启动 - 参见:
-
setEndTime
指定流的结束时间。必须在启动流之前设置结束时间。
在结束时间时,流将关闭。
- 参数:
-
endTime
- 结束时间,不能为空 - 抛出:
-
IllegalStateException
- 如果流已经启动 - 参见:
-
start
void start()开始执行操作。操作在当前线程中执行。
要停止流,请使用
close()
方法。- 抛出:
-
IllegalStateException
- 如果流已经启动或关闭
-
startAsync
void startAsync()开始异步执行操作。操作在单独的线程中执行。
要停止流,请使用
close()
方法。- 抛出:
-
IllegalStateException
- 如果流已经启动或关闭
-
awaitTermination
阻塞直到所有操作完成,或流关闭,或超时发生,或当前线程被中断,以先发生者为准。- 参数:
-
timeout
- 等待的最长时间,不能为空 - 抛出:
-
IllegalArgumentException
- 如果超时为负数 -
InterruptedException
- 在等待时被中断 - 参见:
-
awaitTermination
阻塞直到所有操作完成,或流关闭,或当前线程被中断,以先发生者为准。- 抛出:
-
InterruptedException
- 在等待时被中断 - 参见:
-