- 所有超接口:
-
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阻塞,直到所有操作完成,或流关闭,或当前线程被中断,以先发生者为准。voidawaitTermination(Duration timeout) 阻塞,直到所有操作完成,或流关闭,或超时发生,或当前线程被中断,以先发生者为准。voidclose()释放与此流相关的所有资源。void注册在流关闭时执行的操作。void注册在发生异常时执行的操作。voidonEvent(String eventName, Consumer<RecordedEvent> action) 注册在所有匹配名称的事件上执行的操作。voidonEvent(Consumer<RecordedEvent> action) 注册在流中所有事件上执行的操作。void注册在流刷新后执行的操作。default voidonMetadata(Consumer<MetadataEvent> action) 注册在流中新元数据到达时执行的操作。static EventStream从文件创建事件流。static EventStream从当前Java虚拟机(JVM)的存储库创建流。static EventStreamopenRepository(Path directory) 从磁盘存储库创建事件流。boolean注销操作。voidsetEndTime(Instant endTime) 指定流的结束时间。voidsetOrdered(boolean ordered) 指定事件按照它们提交到流的时间按时间顺序到达的顺序。voidsetReuse(boolean reuse) 指定onEvent(Consumer)操作中的事件对象可以重用。voidsetStartTime(Instant startTime) 指定流的开始时间。voidstart()开始处理操作。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- 在等待时被中断 - 参见:
-