Class ExecutionListener
- All Implemented Interfaces:
AutoCloseable
The following example prints the characters of every executed statement of simple JavaScript
loop.
Prints the following result:
Context context = Context.create("js");
ExecutionListeners listener = ExecutionListeners.newBuilder()
.onEnter((e) -> System.out.println(
e.getLocation().getCharacters()))
.statements(true)
.attach(context.getEngine());
context.eval("js", "for (var i = 0; i < 2; i++);");
listener.close();
i = 0 i < 2 i++ i < 2 i++ i < 2
Creation and Closing
An execution listener builder can be created by first invokingnewBuilder()
. At least
one event consumer and one filtered source element needs to be enabled. To complete the listener
attachment ExecutionListener.Builder.attach(Engine)
needs to be invoked. Attach
may be invoked multiple times for one builder.
All execution listeners are automatically closed when the engine closed
.
To close a listener earlier close()
may be invoked. Execution listeners are
AutoCloseable
and can therefore be used in try-with-resources blocks.
Event Consumers
The following event consumers can be set for an execution listener:OnEnter
: An event that is notified when an execution of an element is entered. This event is consumed before any input values are executed.OnReturn
: An event that is notified when an execution of an element was entered and completed.
IllegalArgumentException
will be
thrown by the builder when it is attached
.
Event consumers may throw any Java host exception. Such exceptions will be reported to the
context as PolyglotException
instances. The thrown exception may be accessed using
PolyglotException.asHostException()
.
Event Data
For every event that is consumed thesource location
and
root name
data is available. Other event data will return
null
by default.
The collection of the following event data may be enabled:
Return values
: Enables access toreturn values
inOnReturn
events.Input values
: Enables access toinput values
inOnReturn
events.Errors
: Enables access toerrors
inOnReturn
events.
Provided event instances may escape the event consumer and remain usable until the engine is closed.
Event Filters
Execution listeners can be applied to the following source elements:Roots
: Filter for marked program locations that represent a root of a function, method or closure.Statements
: Filter for marked program locations that represent a statement.Expressions
: Filter for marked program locations that represent an expression.
IllegalArgumentException
will be thrown by the builder when it is attached
. Not all source
elements may be supported by a language. If the language does not support listening to a source
element then no events will be triggered.
If multiple source elements are enabled, multiple or one event may be reported per source location. If this behavior is not desirable than multiple execution listeners for each source element can be created and attached.
By default the execution listener is applied to all sources
that were loaded. A
source filter
may be attached to limit the number of
sources that will trigger events.
Performance
The peak performance overhead of execution listeners depend on the granularity of the filter. Roots can be collected more efficiently than statement or expression events due to their frequency. If additional event data is collected then the peak performance overhead of execution listeners is significant. It is not recommended to collect additional event data when running production workloads.
Attaching
and closing
execution listeners are
expensive operations and typically require to traverse through all loaded code. Code that was
previously optimized will be deoptimized in the process. It is most efficient to attach an
execution listener before any code is executed and let execution listeners automatically close
with the engine.
Compatibility
Event execution order and granularity of events are language specific and may change without notice. There are no compatibility guarantees for that provided by the polyglot SDK. Certain language implementations may do so. Please see the language implementation documentation for further details.Use-cases
Execution listeners are designed as simple API for polyglot embedders to capture cross cutting concerns of the execution of programs. For example, it can be used to count all statements executed in order to detect potentially malicious code. It is not designed to be an API for implementing fully fledged tools. The Truffle instrumentation framework should be used for that purpose instead.- Since:
- 19.0
-
Nested Class Summary
Modifier and TypeClassDescriptionfinal class
A builder used to construct execution events. -
Method Summary
Modifier and TypeMethodDescriptionvoid
close()
Closes and detaches this execution listener from the engine.static ExecutionListener.Builder
Creates a builder that can be used to attach execution listeners.
-
Method Details
-
close
public void close()Closes and detaches this execution listener from the engine. After an execution listener was closed no further events will be reported.Attaching
andclosing
execution listeners are expensive operations and typically require to traverse through all loaded code. Code that was previously optimized will be deoptimized in the process. It is most efficient to attach an execution listener before any code is executed and let execution listeners automatically close with the engine.- Specified by:
close
in interfaceAutoCloseable
- Since:
- 19.0
- See Also:
-
newBuilder
Creates a builder that can be used to attach execution listeners. The returned Builder instance is not thread-safe.A minimal example on how to build and attach a listener:
ExecutionListeners listener = ExecutionListeners.newBuilder() .onEnter((e) -> ...) .statements(true) .attach(context.getEngine());
- Since:
- 19.0
- See Also:
-