RecordingStream (Java SE 26 & JDK 26)
Description: declaration: module: jdk.jfr, package: jdk.jfr.consumer, class: RecordingStream
Keywords: jdk.jfr.consumer.RecordingStream class

# Class RecordingStream

java.lang.Object
jdk.jfr.consumer.RecordingStream

All Implemented Interfaces:
  `AutoCloseable, EventStream`

public final class RecordingStream extends Object implements AutoCloseable, EventStream
A recording stream produces events from the current JVM (Java Virtual Machine).

The following example shows how to record events using the default configuration and print the Garbage Collection, CPU Load and JVM Information event to standard out.

    Configuration c = Configuration.getConfiguration("default");
    try (var rs = new RecordingStream(c)) {
        rs.onEvent("jdk.GarbageCollection", System.out::println);
        rs.onEvent("jdk.CPULoad", System.out::println);
        rs.onEvent("jdk.JVMInformation", System.out::println);
        rs.start();
    }

Since:
  14

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `RecordingStream()`
  Creates an event stream for the current JVM (Java Virtual Machine).
  `RecordingStream(Configuration configuration)`
  Creates a recording stream using settings from a configuration.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `void`
  `awaitTermination()`
  Blocks until all actions are completed, or the stream is closed, or the current thread is interrupted, whichever happens first.
  `void`
  `awaitTermination(Duration timeout)`
  Blocks until all actions are completed, or the stream is closed, or the timeout occurs, or the current thread is interrupted, whichever happens first.
  `void`
  `close()`
  Closes this resource, relinquishing any underlying resources.
  `EventSettings`
  `disable(Class<? extends Event> eventClass)`
  Disables event.
  `EventSettings`
  `disable(String name)`
  Disables event with the specified name.
  `void`
  `dump(Path destination)`
  Writes recording data to a file.
  `EventSettings`
  `enable(Class<? extends Event> eventClass)`
  Enables event.
  `EventSettings`
  `enable(String name)`
  Enables the event with the specified name.
  `void`
  `onClose(Runnable action)`
  Registers an action to perform when the stream is closed.
  `void`
  `onError(Consumer<Throwable> action)`
  Registers an action to perform if an exception occurs.
  `void`
  `onEvent(String eventName, Consumer<RecordedEvent> action)`
  Registers an action to perform on all events matching a name.
  `void`
  `onEvent(Consumer<RecordedEvent> action)`
  Registers an action to perform on all events in the stream.
  `void`
  `onFlush(Runnable action)`
  Registers an action to perform after the stream has been flushed.
  `void`
  `onMetadata(Consumer<MetadataEvent> action)`
  Registers an action to perform when new metadata arrives in the stream.
  `boolean`
  `remove(Object action)`
  Unregisters an action.
  `void`
  `setEndTime(Instant endTime)`
  Specifies the end time of the stream.
  `void`
  `setMaxAge(Duration maxAge)`
  Determines how far back data is kept for the stream.
  `void`
  `setMaxSize(long maxSize)`
  Determines how much data is kept for the stream.
  `void`
  `setOrdered(boolean ordered)`
  Specifies that events arrive in chronological order, sorted by the time they were committed to the stream.
  `void`
  `setReuse(boolean reuse)`
  Specifies that the event object in an `EventStream.onEvent(Consumer)` action can be reused.
  `void`
  `setSettings(Map<String,String> settings)`
  Replaces all settings for this recording stream.
  `void`
  `setStartTime(Instant startTime)`
  Specifies the start time of the stream.
  `void`
  `start()`
  Starts processing of actions.
  `void`
  `startAsync()`
  Starts asynchronous processing of actions.
  `boolean`
  `stop()`
  Stops the recording stream.

  ### Methods declared in class Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`
  Modifier and Type
  Method
  Description
  `protected Object`
  `clone()`
  Creates and returns a copy of this object.
  `boolean`
  `equals(Object obj)`
  Indicates whether some other object is "equal to" this one.
  `protected void`
  `finalize()`
  Deprecated, for removal: This API element is subject to removal in a future version.
  Finalization is deprecated and subject to removal in a future release.
  `final Class<?>`
  `getClass()`
  Returns the runtime class of this `Object`.
  `int`
  `hashCode()`
  Returns a hash code value for this object.
  `final void`
  `notify()`
  Wakes up a single thread that is waiting on this object's monitor.
  `final void`
  `notifyAll()`
  Wakes up all threads that are waiting on this object's monitor.
  `String`
  `toString()`
  Returns a string representation of the object.
  `final void`
  `wait()`
  Causes the current thread to wait until it is awakened, typically by being notified or interrupted.
  `final void`
  `wait(long timeoutMillis)`
  Causes the current thread to wait until it is awakened, typically by being notified or interrupted, or until a certain amount of real time has elapsed.
  `final void`
  `wait(long timeoutMillis, int nanos)`
  Causes the current thread to wait until it is awakened, typically by being notified or interrupted, or until a certain amount of real time has elapsed.

- ## Constructor Details

  - ### RecordingStream

    public RecordingStream()
    Creates an event stream for the current JVM (Java Virtual Machine).
    Throws:
      `IllegalStateException` - if Flight Recorder can't be created (for example, if the Java Virtual Machine (JVM) lacks Flight Recorder support, or if the file repository can't be created or accessed)

  - ### RecordingStream

    public RecordingStream(Configuration configuration)
    Creates a recording stream using settings from a configuration.

    The following example shows how to create a recording stream that uses a predefined configuration.

        var c = Configuration.getConfiguration("default");
        try (var rs = new RecordingStream(c)) {
            rs.onEvent(System.out::println);
            rs.start();
        }

    Parameters:
      `configuration` - configuration that contains the settings to use, not `null`
    Throws:
      `IllegalStateException` - if Flight Recorder can't be created (for example, if the Java Virtual Machine (JVM) lacks Flight Recorder support, or if the file repository can't be created or accessed)
    See Also:
      - `Configuration`

- ## Method Details

  - ### enable

    public EventSettings enable(String name)
    Enables the event with the specified name.

    If multiple events have the same name (for example, the same class is loaded in different class loaders), then all events that match the name are enabled. To enable a specific class, use the `enable(Class)` method or a `String` representation of the event type ID.

    Parameters:
      `name` - the settings for the event, not `null`
    Returns:
      an event setting for further configuration, not `null`
    See Also:
      - `EventType`

  - ### setSettings

    public void setSettings(Map<String,String> settings)
    Replaces all settings for this recording stream.

    The following example records 20 seconds using the "default" configuration and then changes settings to the "profile" configuration.

        Configuration defaultConfiguration = Configuration.getConfiguration("default");
        Configuration profileConfiguration = Configuration.getConfiguration("profile");
        try (var rs = new RecordingStream(defaultConfiguration)) {
            rs.onEvent(System.out::println);
            rs.startAsync();
            Thread.sleep(20_000);
            rs.setSettings(profileConfiguration.getSettings());
            Thread.sleep(20_000);
        }

    Parameters:
      `settings` - the settings to set, not `null`
    See Also:
      - `Recording.setSettings(Map)`

  - ### enable

    public EventSettings enable(Class<? extends Event> eventClass)
    Enables event.
    Parameters:
      `eventClass` - the event to enable, not `null`
    Returns:
      an event setting for further configuration, not `null`
    Throws:
      `IllegalArgumentException` - if `eventClass` is an abstract class or not a subclass of `Event`

  - ### disable

    public EventSettings disable(String name)
    Disables event with the specified name.

    If multiple events with same name (for example, the same class is loaded in different class loaders), then all events that match the name are disabled. To disable a specific class, use the `disable(Class)` method or a `String` representation of the event type ID.

    Parameters:
      `name` - the settings for the event, not `null`
    Returns:
      an event setting for further configuration, not `null`

  - ### disable

    public EventSettings disable(Class<? extends Event> eventClass)
    Disables event.
    Parameters:
      `eventClass` - the event to enable, not `null`
    Returns:
      an event setting for further configuration, not `null`
    Throws:
      `IllegalArgumentException` - if `eventClass` is an abstract class or not a subclass of `Event`

  - ### setMaxAge

    public void setMaxAge(Duration maxAge)
    Determines how far back data is kept for the stream.

    To control the amount of recording data stored on disk, the maximum length of time to retain the data can be specified. Data stored on disk that is older than the specified length of time is removed by the Java Virtual Machine (JVM).

    If neither the maximum limit nor the maximum age is set, the size of the recording may grow indefinitely if events are not consumed.

    Parameters:
      `maxAge` - the length of time that data is kept, or `null` if infinite
    Throws:
      `IllegalArgumentException` - if `maxAge` is negative
      `IllegalStateException` - if the recording is in the `CLOSED` state

  - ### setMaxSize

    public void setMaxSize(long maxSize)
    Determines how much data is kept for the stream.

    To control the amount of recording data that is stored on disk, the maximum amount of data to retain can be specified. When the maximum limit is exceeded, the Java Virtual Machine (JVM) removes the oldest chunk to make room for a more recent chunk.

    If neither maximum limit or the maximum age is set, the size of the recording may grow indefinitely.

    The size is measured in bytes.

    Parameters:
      `maxSize` - the amount of data to retain, `0` if infinite
    Throws:
      `IllegalArgumentException` - if `maxSize` is negative
      `IllegalStateException` - if the recording is in `CLOSED` state

  - ### setReuse

    public void setReuse(boolean reuse)
    Description copied from interface: `EventStream`
    Specifies that the event object in an `EventStream.onEvent(Consumer)` action can be reused.

    If reuse is set to `true`, an action should not keep a reference to the event object after the action has completed.

    Specified by:
      `setReuse` in interface `EventStream`
    Parameters:
      `reuse` - `true` if an event object can be reused, `false` otherwise

  - ### setOrdered

    public void setOrdered(boolean ordered)
    Description copied from interface: `EventStream`
    Specifies that events arrive in chronological order, sorted by the time they were committed to the stream.
    Specified by:
      `setOrdered` in interface `EventStream`
    Parameters:
      `ordered` - if event objects arrive in chronological order to `EventStream.onEvent(Consumer)`

  - ### setStartTime

    public void setStartTime(Instant startTime)
    Description copied from interface: `EventStream`
    Specifies the start time of the stream.

    The start time must be set before starting the stream

    Specified by:
      `setStartTime` in interface `EventStream`
    Parameters:
      `startTime` - the start time, not `null`
    See Also:
      - `EventStream.start()`
      - `EventStream.startAsync()`

  - ### setEndTime

    public void setEndTime(Instant endTime)
    Description copied from interface: `EventStream`
    Specifies the end time of the stream.

    The end time must be set before starting the stream.

    At end time, the stream is closed.

    Specified by:
      `setEndTime` in interface `EventStream`
    Parameters:
      `endTime` - the end time, not `null`
    See Also:
      - `EventStream.start()`
      - `EventStream.startAsync()`

  - ### onEvent

    public void onEvent(String eventName, Consumer<RecordedEvent> action)
    Description copied from interface: `EventStream`
    Registers an action to perform on all events matching a name.
    Specified by:
      `onEvent` in interface `EventStream`
    Parameters:
      `eventName` - the name of the event, not `null`
      `action` - an action to perform on each `RecordedEvent` matching the event name, not `null`

  - ### onEvent

    public void onEvent(Consumer<RecordedEvent> action)
    Description copied from interface: `EventStream`
    Registers an action to perform on all events in the stream.

    To perform an action on a subset of event types, consider using `EventStream.onEvent(String, Consumer)` and `EventStream.onMetadata(Consumer)` as it is likely more performant than any selection or filtering mechanism implemented in a generic action.

    Specified by:
      `onEvent` in interface `EventStream`
    Parameters:
      `action` - an action to perform on each `RecordedEvent`, not `null`
    See Also:
      - `EventStream.onEvent(Consumer)`
      - `EventStream.onMetadata(Consumer)`

  - ### onFlush

    public void onFlush(Runnable action)
    Description copied from interface: `EventStream`
    Registers an action to perform after the stream has been flushed.
    Specified by:
      `onFlush` in interface `EventStream`
    Parameters:
      `action` - an action to perform after the stream has been flushed, not `null`

  - ### onClose

    public void onClose(Runnable action)
    Description copied from interface: `EventStream`
    Registers an action to perform when the stream is closed.

    If the stream is already closed, the action will be performed immediately in the current thread.

    Specified by:
      `onClose` in interface `EventStream`
    Parameters:
      `action` - an action to perform after the stream is closed, not `null`
    See Also:
      - `EventStream.close()`

  - ### onError

    public void onError(Consumer<Throwable> action)
    Description copied from interface: `EventStream`
    Registers an action to perform if an exception occurs.

    If an action is not registered, an exception stack trace is printed to standard error.

    Registering an action overrides the default behavior. If multiple actions have been registered, they are performed in the order of registration.

    If this method itself throws an exception, resulting behavior is undefined.

    Specified by:
      `onError` in interface `EventStream`
    Parameters:
      `action` - an action to perform if an exception occurs, not `null`

  - ### close

    public void close()
    Description copied from interface: `AutoCloseable`
    Closes this resource, relinquishing any underlying resources. This method is invoked automatically on objects managed by the `try`-with-resources statement.
    Specified by:
      `close` in interface `AutoCloseable`
    Specified by:
      `close` in interface `EventStream`

  - ### remove

    public boolean remove(Object action)
    Description copied from interface: `EventStream`
    Unregisters an action.

    If the action has been registered multiple times, all instances are unregistered.

    Specified by:
      `remove` in interface `EventStream`
    Parameters:
      `action` - the action to unregister, not `null`
    Returns:
      `true` if the action was unregistered, `false` otherwise
    See Also:
      - `EventStream.onEvent(Consumer)`
      - `EventStream.onEvent(String, Consumer)`
      - `EventStream.onFlush(Runnable)`
      - `EventStream.onClose(Runnable)`
      - `EventStream.onError(Consumer)`

  - ### start

    public void start()
    Description copied from interface: `EventStream`
    Starts processing of actions.

    Actions are performed in the current thread.

    To stop the stream, use the `EventStream.close()` method.

    Specified by:
      `start` in interface `EventStream`

  - ### startAsync

    public void startAsync()
    Starts asynchronous processing of actions.

    Actions are performed in a single separate thread.

    To stop the stream, use the `close()` method.

    The following example prints the CPU usage for ten seconds. When the current thread leaves the try-with-resources block the stream is stopped/closed.

        try (var stream = new RecordingStream()) {
            stream.enable("jdk.CPULoad").withPeriod(Duration.ofSeconds(1));
            stream.onEvent("jdk.CPULoad", event -> {
                System.out.println(event);
            });
            stream.startAsync();
            Thread.sleep(10_000);
        }

    Specified by:
      `startAsync` in interface `EventStream`
    Throws:
      `IllegalStateException` - if the stream is already started or closed

  - ### stop

    public boolean stop()
    Stops the recording stream.

    Stops a started stream and waits until all events in the recording have been consumed.

    Invoking this method in an action, for example in the `onEvent(Consumer)` method, could block the stream indefinitely. To stop the stream abruptly, use the `close()` method.

    The following code snippet illustrates how this method can be used in conjunction with the `startAsync()` method to monitor what happens during a test method:

        AtomicBoolean socketUse = new AtomicBoolean();
        try (var r = new RecordingStream()) {
            r.setMaxSize(Long.MAX_VALUE);
            r.enable("jdk.SocketWrite").withoutThreshold();
            r.enable("jdk.SocketRead").withoutThreshold();
            r.onEvent(event -> socketUse.set(true));
            r.startAsync();
            testFoo();
            r.stop();
            if (socketUse.get()) {
                r.dump(Path.of("socket-events.jfr"));
                throw new AssertionError("testFoo() should not use network");
            }
        }

    Returns:
      `true` if recording is stopped, `false` otherwise
    Throws:
      `IllegalStateException` - if the recording is not started or is already stopped
    Since:
      20

  - ### dump

    public void dump(Path destination) throws IOException
    Writes recording data to a file.

    The recording stream must be started, but not closed.

    It's highly recommended that a max age or max size is set before starting the stream. Otherwise, the dump may not contain any events.

    Parameters:
      `destination` - the location where recording data is written, not `null`
    Throws:
      `IOException` - if the recording data can't be copied to the specified location, or if the stream is closed, or not started.
    Since:
      17
    See Also:
      - `setMaxAge(Duration)`
      - `setMaxSize(long)`

  - ### awaitTermination

    public void awaitTermination(Duration timeout) throws InterruptedException
    Description copied from interface: `EventStream`
    Blocks until all actions are completed, or the stream is closed, or the timeout occurs, or the current thread is interrupted, whichever happens first.
    Specified by:
      `awaitTermination` in interface `EventStream`
    Parameters:
      `timeout` - the maximum time to wait, not `null`
    Throws:
      `InterruptedException` - if interrupted while waiting
    See Also:
      - `EventStream.start()`
      - `EventStream.startAsync()`
      - `Thread.interrupt()`

  - ### awaitTermination

    public void awaitTermination() throws InterruptedException
    Description copied from interface: `EventStream`
    Blocks until all actions are completed, or the stream is closed, or the current thread is interrupted, whichever happens first.
    Specified by:
      `awaitTermination` in interface `EventStream`
    Throws:
      `InterruptedException` - if interrupted while waiting
    See Also:
      - `EventStream.start()`
      - `EventStream.startAsync()`
      - `Thread.interrupt()`

  - ### onMetadata

    public void onMetadata(Consumer<MetadataEvent> action)
    Registers an action to perform when new metadata arrives in the stream. The event type of an event always arrives sometime before the actual event. The action must be registered before the stream is started.

    The following example shows how to listen to new event types, register an action if the event type name matches a regular expression and increase a counter if a matching event is found. A benefit of using an action per event type, instead of the generic `onEvent(Consumer)` method, is that a stream implementation can avoid reading events that are of no interest.

        static long count = 0;
        public static void main(String... args) throws Exception {
            String regExp = args[0];
            var pr = Pattern.compile(regExp).asMatchPredicate();
            Configuration c = Configuration.getConfiguration("default");
            try (var s = new RecordingStream(c)) {
                s.setOrdered(false);
                s.onMetadata(metadata -> metadata.getAddedEventTypes()
                 .stream().map(EventType::getName).filter(pr)
                 .forEach(eventName -> s.onEvent(eventName, event -> count++)));
                s.startAsync();
                System.out.println("Running recording for 5 s. Please wait.");
                s.awaitTermination(Duration.ofSeconds(5));
                System.out.println(count + " events matches " + regExp);
            }
        }

    Specified by:
      `onMetadata` in interface `EventStream`
    Parameters:
      `action` - to perform, not `null`
    Throws:
      `IllegalStateException` - if an action is added after the stream has started
    Since:
      16