Note: This is a draft document that describes functionality that is expected to be supported in Java RTS 2.1. The DTrace provider and probe functionality and related documentation are being provided as Early-Access starting with 2.0 Update 1 to encourage trial use, evaluation, and feedback. If you have any suggestions or questions on either the functionality or the documentation of the DTrace provider for Java RTS, please contact the Java RTS team. This document describes the DTrace probe provider functionality for Sun Java Real-Time System. This functionality allows real-time developers to observe, debug, and tune their real-time applications. With the jrts provider, it is possible to monitor activities from priority updates to memory area operations, as well as RTGC cycles, all without any modification to the running application. It is possible to synchronize a DTrace script with the start of the Java virtual machine, but a DTrace script can also be launched to monitor an already running virtual machine.ContentsHow to Use the Java RTS DTrace Provider Probes Related to Schedulables [Readme File] [Installation Guide] [Release Notes] [Compilation Guide] [Garbage Collection Guide] [Technical Information] [Practical Introduction to Achieving Determinism] How to Use the Java RTS DTrace ProviderFirst of all, it is strongly recommended to read the DTrace documentation available here. The rest of this document assumes that the reader is familiar with the D language and how DTrace works.The jrts provider is a statically defined user provider working through the standard pid provider. To enable a jrts probe to monitor a real-time virtual machine, the provider name to use is jrts followed by the process ID of the virtual machine. For instance, to enable the probe thread-start in the JVM running in process 1245, the clause is written as follows:
jrts1245:::thread-start { /* your action */ }
You can avoid hard coding the pid in the clause by using a variable or a
script argument to store the pid of the targeted VM. In the sample scripts provided
at the end of this document, the variable
To be able to compile a D script using the jrts provider, the targeted VM must be
running and the probes available. If the Java RTS VM is started with the -XX:+PauseAtStartup
option on the command line, it will stop itself as soon as all the probes are available and
before starting to execute Java code. It will also create a file in the current directory
called
You can also start the Java RTS VM directly from a
dtrace -s <your_DTrace_script> -Z -c "<vm_launch_command>"
Note that because of the usage of the ProbesThe probes supplied by the jrts provider are presented here in eight different sections, depending on the concept they are related to:Notation: In this document, the probes are described like functions to facilitate reading the arguments. For example, a probe can be declared this way:
probe1(id1,name,len)
In this case the probe name is
This probe has three arguments defined,jrts<pid>:::probe1 { /* your action */ } id1 , name , and len .
These arguments are accessible through the DTrace built-in variables args[0] ,
args[1] , and args[2] , respectively.
Time values: The time values provided by probesmonitor-wait and handler-release-* are
absolute time expressed in nanoseconds. They are based on the same time source
(the Solaris high resolution clock) as the built-in variable timestamp provided by DTrace.
Thus, time values passed by the jrts provider are comparable with values read from the
timestamp variable.
String values: A number of probes of the jrts provider have arguments of typechar * . These arguments are not
guaranteed to be NULL-terminated arrays of char , but they are always followed by an argument that
provides the size of the array of char . To copy these arrays of char from the process address space to a DTrace
variable, use the copyinstr() function, specifying the address and the size of the array of char .
Probes Related to SchedulablesThe schedulable probes are common to all schedulables (threads and handlers). Their goal is to ease the analysis of the scheduling by providing additional information about priority changes and blocking.priority-change(uintptr_t schedulable_id, int schedulable_type, int new_priority) This probe is triggered by an explicit priority change to an RTSJ schedulable. The sched:change-pri probe provided by the Solaris kernel is not sufficient because it does not provide enough information to make the distinction between explicit priority changes and boosting/unboosting caused by the priority inheritance protocol (see the two probes below). The schedulable_type argument specifies if the priority change applies to a thread or an instance ofAsyncEventHandler .
The possible values for the schedulable_type are shown in
the table below.
If the modification applies to a thread, schedulable_id is the thread ID. For a handler, schedulable_id is the opaque ID for this handler. The new_priority argument contains the requested new priority. priority-boost(int boosted_thread_tid, int new_priority, uintptr_t lock_id) This probe fires when the current thread is boosting the thread boosted_thread_id to the priority new_priority because of a contention on lock lock_id.priority-unboost(int thread_id, int new_priority) This probe fires when thread thread_id has its priority changed to new_priority due to an unboosting operation.monitor-contended-enter(uintptr_t monitor_id, char* klass_name, uintptr_t len) This probe fires when the current thread is trying to enter a contended monitor. The monitor_id argument is an opaque ID to identify the monitor, and the klass_name argument provides the monitor class name. If the monitor is not associated with a Java object, the klass_name argument is NULL and the len argument is zero.monitor-contended-entered(uintptr_t monitor_id, char* klass_name, uintptr_t len) This probe fires when the current thread successfully enters the contended monitor identified by the monitor_id argument. The klass_name argument provides the monitor class name. If the monitor is not associated with a Java object, the klass_name argument is NULL and the len argument is zero.monitor-contended-exit(uintptr_t monitor_id, char* klass_name, uintptr_t len) This probe fires when the current thread exits the contended monitor identified by the monitor_id argument. The klass_name argument provides the monitor class name. If the monitor is not associated with a Java object, the klass_name argument is NULL and the len argument is zero.monitor-wait(uintptr_t monitor_id, char* klass_name, uintptr_t len, uintptr_t high_wakeup, uintptr_t low_wakeup) This probe fires when the current thread callswait() on the monitor identified
by the monitor_id argument. The klass_name argument provides the monitor class name.
If the monitor is not associated with a Java object,
the klass_name argument is NULL and the len argument is zero.
The high_wakeup and low_wakeup arguments provide high 32-bits and low 32-bits of a 64-bit
signed integer containing the wake-up time for the wait() call.
monitor-waited(uintptr_t monitor_id, char* klass_name, uintptr_t len) This probe fires when the current thread completes its call towait() on the monitor
identified by the monitor_id argument. The klass_name argument provides the monitor class name.
If the monitor is not associated with a Java object,
the klass_name argument is NULL and the len argument is zero.
monitor-notify(uintptr_t monitor_id, char* klass_name, uintptr_t len) This probe fires when the current thread callsnotify() on the monitor
identified by the monitor_id argument and at least one thread is
waiting on this monitor. The klass_name argument provides the monitor class name.
If the monitor is not associated with a Java object,
the klass_name argument is NULL and the len argument is zero.
monitor-notifyAll(uintptr_t monitor_id, char* klass_name, uintptr_t len) This probe fires when the current thread callsnotifyAll() on the monitor
identified by the monitor_id argument and at least one thread is waiting
on this monitor. The klass_name argument provides the monitor class name.
If the monitor is not associated with a Java object,
the klass_name argument is NULL and the len argument is zero.
The memory probes are related to the memory areas introduced by the Real-Time Specification for Java (RTSJ). The goal of these probes is to help track the changes of the allocation context of a schedulable, and to monitor all the enter/exit operations performed on a given scoped memory area. memarea-change(uintptr_t memarea_id, int memarea_type) This probe is triggered every time a thread changes its current allocation context. The memarea_id argument provides the ID of the new allocation context for the current thread. The memarea_type argument contains the type of the new allocation context. The possible values for the memarea_type argument are shown below.
memarea-enter(uintptr_t memarea_id, int memarea_type) This probe tracks all enters to a memory area. The memarea_id argument contains the ID of the entered memory area. The memarea_type argument provides the type of entered memory area, with the possible values as shown in this table.memarea-exit(uintptr_t memarea_id, int memarea_type) This probe tracks all exits from a memory area. The memarea_id argument contains the ID of the exited memory area. The memarea_type argument provides the type of exited memory area, with the possible values as shown in this table.scopedmem-creation(uintptr_t memarea_id, char* klass_name, int len, unsigned long high_requested_size, unsigned long low_requested_size, unsigned long high_real_size, unsigned long low_real_size) This probe is fired when a new instance ofScopedMemoryArea
is created. The memarea_id argument is an opaque ID that identifies this
memory area in other probes. The klass_name argument
provides the name of the class used to create the ScopedMemoryArea
instance. The high_requested_size and low_requested_size arguments
are the high 32-bits and low 32-bits of a 64-bit signed integer containing the maximum size requested
by the application in the ScopedMemory constructor. The high_real_size
and low_real_size arguments are the high 32-bits and low 32-bits of a 64-bit signed integer
containing the real size of the memory area allocated from the backing store
for this scoped memory area. (Depending on the implementation, this
value can be greater than the size viewed by the application.)
scopedmem-first-enter(uintptr_t memarea-id) This probe tracks the first enter to a scoped memory area. On a first enter,scopedmem-first-enter is triggered
before memarea-enter.
Because of the introduction of the "fireable" status, probe
scopedmem-last-exit(uintptr_t memarea-id) This probes tracks the last exit from a scoped memory area. On an exit,scopedmem-last-exit is triggered after
memarea-exit .
Because of the introduction of the "fireable" status, probe
scopedmem-finalization(uintptr_t memarea-id) This probe is triggered every time the VM detects that it has to execute finalizers before clearing a scoped memory area.Probes Related to ThreadsThe thread-related probes concernThread , RealtimeThread ,
and NoHeapRealtimeThread instances.
Going further than thread start and end, they provide information about
periodic execution and interruption (Asynchronous Transfer of Control, or ATC).
thread-period-change(int thread_id, unsigned long high_new_period, unsigned long low_new_period) This probe is triggered when a thread's period is modified (not when this change takes effect). This probe also fires when the thread's release policy is changed from periodic to aperiodic. In this last case, the new_period argument is equal to zero. The high_new_period and low_new_period arguments are the high 32-bits and low 32-bits of a 64-bit signed integer containing the value of the new period.thread-deschedule-periodic(int thread_id) This probe fires whendeschedulePeriodic() is performed on the thread
identified by the thread_id argument. If the deschedulePeriodic()
method is invoked on a non-periodic thread or thread not alive, the
method has no effect and the probe doesn't fire.
thread-schedule-periodic(int thread_id) This probe fires whenschedulePeriodic() is performed on the thread
identified by the thread_id argument. If the schedulePeriodic()
method is invoked on a non-periodic thread or thread that is not alive, the
method has no effect and the probe does not fire.
thread-aie-fired(int thread_id) This probe fires when an Asynchronous Interrupted Exception is generated. The thread_id is the ID of the thread which will receive the AIE. If the thread is not alive then thread_id will be zero.thread-aie-delivered() This probe fires when a pending Asynchronously Interrupted Exception is being propagated because the thread is executing AI-enabled code with an AIE pending.thread-aie-cleared() This probe fires when an Asynchronously Interrupted Exception is cleared.thread-start(int thread_id, int thread_type, char *klass_name, int klass_len, char *thread_name, int name_len) This probe fires when thestart() method is invoked on a thread.
The thread_id argument identifies the thread being started. The
thread_type argument provides the type of the thread being
started. The possible values for the thread_type argument
are shown below.
The klass_name argument provides the thread class name, and the klass_len argument the length of the class name. The thread_name argument provides the thread's name, and the name_len argument the length of the thread's name. thread-begin() A thread fires this probe just before starting the execution of itsrun() method.
thread-end() A thread fires this probe just after the completion of itsrun() method.
thread-set-name(int thread_id, char *new_thread_name, int new_name_length) This probes fires when the current thread sets the name of the thread with thread ID thread_id to new_thread_name. If the renamed thread is not alive, the thread_id is zero.thread-wfnp-enter(int flag_interruptible) This probe is fired by a thread invoking thewaitForNextPeriod() or
waitForNextPeriodInterruptible() method. The flag_interruptible argument
specifies which method is invoked.
thread-wfnp-exit(int return_status) This probe is fired by a thread when it returns from awaitForNextPeriod()
call. The return_status argument provides the value returned by
the waitForNextPeriod() method.
thread-deadline-miss(uintptr_t handler_id) This probe fires when a thread's deadline miss causes the release of its deadline miss handler. The handler_id argument identifies the handler to be released.Probes Related to HandlersThe handler probes are related to instances ofAsyncEventHandler .
These probes aim to expose all the steps
from the event's firing to the execution of the application's logic:
firing, release policy, binding, and so forth.
They also allow tracking of the creation and destruction of server threads
in order to help the developer in sizing the server pools.
event-fire(uintptr_t event_id) This probe fires when the event identified by the event_id argument is fired.handler-creation(uintptr_t handler_id, char *klass_name, int len, int noheap) This probe fires after the creation of anAsyncEventHandler instance to
provide useful information about this handler. The handler_id argument
identifies this handler in other probes. The klass_name argument provides
the handler class name. If the noheap argument is true, the
handler type is noheap; if false, the handler type is heap.
handler-release-accepted(uintptr_t handler_id, unsigned long high_real_release_time, unsigned long low_real_release_time, unsigned long high_effective_release_time, unsigned long low_effective_release_time) This probe fires when the release of a handler has been accepted. This release could have been caused by the firing of an event, a timer, or a deadline miss. The handler_id argument contains the ID of the handler being released. The high_real_release_time and low_real_release_time arguments are the high 32-bits and low 32-bits of a 64-bit signed integer containing the time when the release request occurred, while the high_effective_release_time and low_effective_release arguments are the high 32-bits and low 32-bits of a 64-bit signed integer containing the time the handler will actually be released. The real release time and the effective release time are different when the release of the handler has been delayed because of a Minimum Interarrival Time policy enforcement. In the other cases, the values are equal.handler-release-replace(uintptr_t handler_id, unsigned long high_real_release_time, unsigned long low_real_release_time, unsigned long high_effective_release_time, unsigned long low_effective_release_time) This probe fires when the release of a handler will replace a previously accepted release in the pending release queue. This release could have been caused by the firing of an event, a timer, or a deadline miss. The handler_id argument contains the ID of the handler being released. The high_real_release_time and low_real_release_time arguments are the high 32-bits and low 32-bits of a 64-bit signed integer containing the time when the release request occurred, while the high_effective_release_time and low_effective_release arguments are the high 32-bits and low 32-bits of a 64-bit signed integer containing the time the handler will actually be released. The real release time and the effective release time are different when the release of the handler has been delayed because of a Minimum Interarrival Time policy enforcement. In other cases, the values are equal.handler-release-rejected(uintptr_t handler_id, unsigned long high_release_time, unsigned long low_release_time, int policy) This probe fires when the release of a handler has been refused. The handler_id argument provides the ID of the handler, and the high_release_time and low_release_time arguments are the high 32-bits and low 32-bits of a 64-bit signed integer containing the time of the release being rejected. The policy argument provides the release policy being considered for this release. The possible values for the policy argument are shown below.
handler-release-ignored(uintptr_t handler_id, unsigned long high_release_time, unsigned long low_release_time, int policy) This probe fires when the release of a handler has been ignored. The handler_id argument provides the ID of the handler, and the high_release_time and low_release_time arguments are the high 32-bits and low 32-bits of a 64-bit signed integer containing the time of the release being ignored. The policy argument provides the release policy being considered for this release. The possible values for the policy argument are shown in this table.server-thread-binding(uintptr_t handler_id) This probe fires when a server thread binds itself to the handler identified by the handler_id argument. Server threads executingBoundAsyncEventHandler fire this probe only once.
server-thread-unbinding(uintptr_t handler_id) This probe fires when a server thread unbinds itself from the handler identified by the handler_id argument. Server threads executingBoundAsyncEventHandler fire this probe only once.
server-thread-creation(int noheap) This probe fires when a new server thread is created. The noheap argument specifies if the server thread is an instance ofNoHeapRealtimeThread or not. This probe does not
fire if the thread is intended to be associated with a BoundAsyncEventHandler .
server-thread-destruction(int noheap) This probe fires when a new server thread is destroyed. The noheap argument specifies if the server thread is an instance ofNoHeapRealtimeThread or not. This probe doesn't
fire if the thread was associated with a BoundAsyncEventHandler .
server-thread-wakeup(int thread_id, int priority) This probe fires when the current thread wakes up the server thread with the thread ID thread_id. The second argument specifies at which priority this server thread has been awakened (or zero if the server thread is a bound server thread).handler-start(uintptr_t handler_id) This probe fires when a server thread starts the execution of the main loop of the handler logic (not thehandleAsyncEvent() method, but an outer loop that tracks
the fire count and any needed delay due to MIT violation).
handler-end(uintptr_t handler_id) This probe fires when a server thread ends the execution of the main loop of the handler logic (not thehandleAsyncEvent() method, but an outer loop that tracks
the fire count and any needed delay due to MIT violation).
handler-deadline-miss(uintptr_t handler_id) This probe fires when a handler's deadline miss causes the release of its deadline miss handler. The handler_id argument identifies the handler to be released.Probes Related to CompilationThe compilation probes help the developer to track when compilations occur for a given class, method, or type of thread. They also provide information about the patching of code due to late resolution of symbols.method-compile-begin(char *klass_name, int klass_name_length, char *method_name, int method_name_length, char *method_signature, int method_signature_length, int thread_type) This probe is triggered when the compilation of a method starts. The first 6 arguments designate the method to be compiled. The thread_type argument indicates for which thread type this method will be compiled.method-compile-end(char *klass_name, int lass_name_length, char *method_name, int method_name_length, char *method_signature, int method_signature_length, int success, int thread_type) This probe is triggered when the compilation of a method ends. The first 6 arguments designate the method that was compiled. The thread_type argument indicates for which thread type this method was compiled. The success argument indicates if the compilation was sucessful or not.compiler-patching-klass(char *in_klass_name, int in_klass_name_length, char *in_method_name, int in_method_name_length, char *in_signature, int in_signature_length, int in_bci, char *to_klass_name, int to_klass_name_length, int thread_type) This probe is triggered on runtime resolution of a class reference in compiled code. The first 7 arguments designate the compiled method in which the symbol is unresolved. The next two give the result of the resolution. The last argument is the type of the thread that triggered the resolution.compiler-patching-tablecall(char *in_klass_name, int in_klass_name_length, char *in_method_name, int in_method_name_length, char *in_signature, int in_signature_length, int in_bci, char *to_klass_name, int to_klass_name_length, char *to_method_name, int to_method_name_length, char *to_signature, int to_signature_length, int thread_type) This probe is triggered on runtime resolution of a virtual/interface method call in compiled code. The first 7 arguments designate the compiled method where the method call is unresolved. The next six give the resolved method. The last argument is the type of the thread that triggered the resolution.compiler-patching-directcall(char *in_klass_name, int in_klass_name_length, char *in_method_name, int in_method_name_length, char *in_signature, int in_signature_length, int in_bci, char *to_klass_name, int to_klass_name_length, char *to_method_name, int to_method_name_length, char *to_signature, int to_signature_length, int thread_type) This probe is triggered on runtime resolution of a direct method call in compiled code. The first 7 arguments designate the compiled method where the direct call method is unresolved. The next six give the resolved method. The last argument is the type of the thread that triggered the resolution.Probes Related to the RTGCThe RTGC probes are related to the activities of the Real-Time Garbage Collector and its worker threads.rtgc-cycle-begin() This probe fires when the RTGC starts a collection cycle.rtgc-cycle-end() This probe fires when the RTGC completes a collection cycle.rtgc-change-priority(int) This probe fires when the RTGC changes its priority.rtgc-worker-thread-start(int worker_id) This probe fires when the VM starts the RTGC worker thread with ID worker_id. The worker_id is an ID for RTGC internal purposes and is not related to the thread_id.rtgc-worker-thread-stop(int worker_id) This probe fires when the VM stops the RTGC worker thread with ID worker_id. The worker_id is an ID for RTGC internal purposes and is not related to the thread_id.Probes Related to ClassesThe class-related probes aim to expose when classes are loaded and the threads that perform those loads. They also provide information about when those classes are initialized, and the type of the thread executing the initialization code. The probes related to class initialization are defined according to the steps described in section 2.17.5 "Detailed Initialization Procedure" of the The Java Virtual Machine Specification book, second edition.class-loaded(char *klass_name, uintptr_t len, void *klass_loader, uintptr_t shared, intptr_t thread_type) This probe fires when a thread loads a new class. The klass_name gives the name of the class being loaded, and klass_loader is an opaque ID for the class loader used to load the class. The thread_type argument is the thread type of the thread performing the class loading. The shared argument is currently not used.class-initialization-required(char *klass_name, uintptr_t len, void *class_loader, intptr_t thread_type) This probe fires when a class is required to be initialized and the current thread proceeds to initiate that initialization. It is placed before step 1 of the initialization process. The klass_name gives the name of the class, and klass_loader is an opaque ID for the class loader that was used to load the class. The thread_type argument is the current thread's type.class-initialization-recursive(char *klass_name, uintptr_t len, void *class_loader, intptr_t thread_type, int wait) This probe fires when a thread that needs to initialize a class discovers that it is already in the process of initializing that class. It corresponds to step 3 of the initialization process. The klass_name gives the name of the class, and klass_loader is an opaque ID for the class loader that was used to load the class. The thread_type argument is the current thread's type. The wait argument is always false.class-initialization-concurrent(char *klass_name, uintptr_t len, void *class_loader, intptr_t thread_type, int wait) This probe fires when the current thread discovers that another thread concurrently completed the initialization of the given class. It corresponds to step 4 of the initialization process. The klass_name gives the name of the initialized class, and klass_loader is an opaque ID for the class loader that was used to load the class. The thread_type argument is the current thread's type. The wait argument is true if the thread had to wait at the beginning of the initialization process.class-initialization-erroneous(char *klass_name, uintptr_t len, void *class_loader, intptr_t thread_type, int wait) This probe fires when the current thread discovers that the given class has already been marked as being in the "erroneous" state and can not be initialized. It corresponds to step 5 of the initialization process. The klass_name gives the name of the class, and klass_loader is an opaque ID for the class loader that was used to load the class. The thread_type argument is the current thread's type. The wait argument is true if the thread had to wait at the beginning of the initialization process.class-initialization-super-failed(char *klass_name, uintptr_t len, void *class_loader, intptr_t thread_type, int wait) This probe fires when the current thread encounters an error trying to initialize the superclass of the given class. It corresponds to step 7 of the initialization process. Of course the initialization attempt for the superclass would have its own probe firings with more information. The klass_name gives the name of the class, and klass_loader is an opaque ID for the class loader that was used to load the class. The thread_type argument is the current thread's type. The wait argument is true if the thread had to wait at the beginning of the initialization process.class-initialization-clinit(char *klass_name, uintptr_t len, void *class_loader, intptr_t thread_type, int wait) This probe fires when the current thread commences execution of the <clinit> method of the given class. It corresponds to step 8 of the initialization process. The klass_name gives the name of the class, and klass_loader is an opaque ID for the class loader that was used to load the class. The thread_type argument is the current thread's type. The wait argument is true if the thread had to wait at the beginning of the initialization process.class-initialization-error(char *klass_name, uintptr_t len, void *class_loader, intptr_t thread_type, int wait) This probe fires when the execution of <clinit> results in an exception being thrown (in response to which the class is marked as being in the "erroneous" state). It corresponds to steps 10 and 11 of the initialization process. The klass_name gives the name of the class, and klass_loader is an opaque ID for the class loader that was used to load the class. The thread_type argument is the current thread's type. The wait argument is true if the thread had to wait at the beginning of the initialization process.class-initialization-end(char *klass_name, uintptr_t len, void *class_loader, intptr_t thread_type, int wait) This probe fires after successful execution of the <clinit> method and the class has been marked as initialized. It corresponds to step 9 of the initialization process. The klass_name gives the name of the class, and klass_loader is an opaque ID for the class loader that was used to load the class. The thread_type argument is the current thread's type. The wait argument is true if the thread had to wait at the beginning of the initialization process.Probes Related to the VMThe VM-related probes aim to expose events that might impact all the activities within the virtual machine. As of today, only the safepoint-related events are exported.safepoint-begin() This probe fires at the beginning of a global safepoint performed by the VM.safepoint-end() This probe fires at the end of a global safepoint performed by the VM.Supported PlatformsThe jrts DTrace probe provider is available only on Solaris 10 platforms (SPARC and x86). The functionality described above is expected to be fully supported with Java RTS 2.1. Early Access of this functionality is provided in Java RTS 2.0 Update 1. Based on Early-Access feedback and additional testing, it is possible there will be changes to the above functionality, such as the addition of new probes or the removal or modification of the probes described above.Sample ScriptsHere are some sample scripts showing how to use the probes described above.
Contact UsPlease report any problems or bugs you might encounter to the Java RTS team. |