This document describes the Java Virtual Machine Profiler Interface (JVMPI) in the Java 2 SDK, Standard Edition. It is intended for tools vendors to develop profilers that work in conjunction with Sun's Java virtual machine* implementation.
Note: The JavaTM Virtual Machine* Profiling Interface (JVMPI) is deprecated as of J2SE 1.5.0. The new JavaTM Virtual Machine Tool Interface (JVMTI) should be used in its place. JVMPI will be removed in the next major release of J2SE.
Please send comments to mailto:[email protected]
Note: VERSION_1 of this interface is implemented in the Classic VM. The Java HotSpot Client VM and the Java HotSpot Server VM both implement VERSION_1_1 (as of Java 2 SDK 1.2.2) or VERSION_1_2 (as of Java 2 SDK 1.4.2) of this interface with Java HotSpot technology. Notes specific to Java Hotspot technology are marked as such.
The JVMPI is a two-way function call interface between the Java virtual machine and an in-process profiler agent. On one hand, the virtual machine notifies the profiler agent of various events, corresponding to, for example, heap allocation, thread start, etc. On the other hand, the profiler agent issues controls and requests for more information through the JVMPI. For example, the profiler agent can turn on/off a specific event notification, based on the needs of the profiler front-end.
[D]The profiler front-end may or may not run in the same process as the profiler agent. It may reside in a different process on the same machine, or on a remote machine connected via the network. The JVMPI does not specify a standard wire protocol. Tools vendors may design wire protocols suitable for the needs of different profiler front-ends.A profiling tool based on JVMPI can obtain a variety of information such as heavy memory allocation sites, CPU usage hot-spots, unnecessary object retention, and monitor contention, for a comprehensive performance analysis.
JVMPI supports partial profiling, i.e a user can selectively profile an application for certain subsets of the time the virtual machine is up and can also choose to obtain only certain types of profiling information.
In the current version of JVMPI, only one agent per virtual machine can be supported.
The user can specify the name of the profiler agent and the options to the profiler agent through a command line option to the Java virtual machine. For example, suppose the user specifies:
java -Xrunmyprofiler:heapdump=on,file=log.txt ToBeProfiledClass
The VM attempts to locate a profiler agent library called myprofiler in Java's library directory:
If the library is not found in the Java library directory, the VM continues to search for the library following the normal library search mechanism of the given platform:
The VM loads the profiler agent library and looks for the entry point:
jint JNICALL JVM_OnLoad(JavaVM *jvm, char *options, void *reserved);
The VM calls theJVM_OnLoadfunction, passing a pointer to theJavaVMinstance as the first argument, and string"heapdump=on,file=log.txt"as the second argument. The third argument toJVM_OnLoadis reserved and set toNULL.
On success, theJVM_OnLoadfunction must returnJNI_OK. If for some reason theJVM_OnLoadfunction fails, it must returnJNI_ERR.
The profiler agent can obtain a function call interface by issuing aGetEnvcall on theJavaVMpointer. For example, the following code retrieves the version of JVMPI interface that is implemented in the Java 2 SDK:
JVMPI_Interface *jvmpi_interface; JNIEXPORT jint JNICALL JVM_OnLoad(JavaVM *jvm, char *options, void *reserved) { int res = (*jvm)->GetEnv(jvm, (void **)&jvmpi_interface, JVMPI_VERSION_1); if (res < 0) { return JNI_ERR; } ... /* use entries in jvmpi_interface */ }
TheJVMPI_Interfacestructure defines the function call interface between the profiler agent and the VM:
/* interface functions */ typedef struct { jint version; /* JVMPI version */ /* ------interface implemented by the profiler------ */ void (*NotifyEvent)(JVMPI_Event *event); /* ------interface implemented by the JVM------ */ jint (*EnableEvent)(jint event_type, void *arg); jint (*DisableEvent)(jint event_type, void *arg); jint (*RequestEvent)(jint event_type, void *arg); void (*GetCallTrace)(JVMPI_CallTrace *trace, jint depth); void (*ProfilerExit)(jint); JVMPI_RawMonitor (*RawMonitorCreate)(char *lock_name); void (*RawMonitorEnter)(JVMPI_RawMonitor lock_id); void (*RawMonitorExit)(JVMPI_RawMonitor lock_id); void (*RawMonitorWait)(JVMPI_RawMonitor lock_id, jlong ms); void (*RawMonitorNotifyAll)(JVMPI_RawMonitor lock_id); void (*RawMonitorDestroy)(JVMPI_RawMonitor lock_id); jlong (*GetCurrentThreadCpuTime)(void); void (*SuspendThread)(JNIEnv *env); void (*ResumeThread)(JNIEnv *env); jint (*GetThreadStatus)(JNIEnv *env); jboolean (*ThreadHasRun)(JNIEnv *env); jint (*CreateSystemThread)(char *name, jint priority, void (*f)(void *)); void (*SetThreadLocalStorage)(JNIEnv *env_id, void *ptr); void * (*GetThreadLocalStorage)(JNIEnv *env_id); void (*DisableGC)(void); void (*EnableGC)(void); void (*RunGC)(void); jobjectID (*GetThreadObject)(JNIEnv *env); jobjectID (*GetMethodClass)(jmethodID mid); /* JNI handle <-> object ID conversions; VERSION_1_1 and newer */ jobject (*jobjectID2jobject)(jobjectID jid); jobjectID (*jobject2jobjectID)(jobject j); /* VERSION_1_2 and newer: */ void (*SuspendThreadList)(jint reqCount, JNIEnv **reqList, jint *results); void (*ResumeThreadList)(jint reqCount, JNIEnv **reqList, jint *results); } JVMPI_Interface;
TheGetEnvfunction returns a pointer to aJVMPI_Interfacewhoseversionfield indicates a JVMPI version that is compatible to the version number argument passed in theGetEnvcall. Note that the value of theversionfield is not necessarily identical to the version argument passed in theGetEnvcall.
TheJVMPI_Interfacereturned byGetEnvhas all the functions set up except forNotifyEvent. The profiler agent must set up theNotifyEventfunction pointer before returning fromJVM_OnLoad.
The VM sends an event by calling NotifyEvent with aJVMPI_Eventdata structure as the argument. The following events are supported:
TheJVMPI_Eventstructure contains the event type, theJNIEnvpointer of the current thread, and other event-specific information. The event specific information is represented as a union of event-specific structures. The JVMPI Events section provides a complete description of all event-specific structures. For now, we show the event-specific structures for class load and class unload below.
typedef struct { jint event_type; /* event_type */ JNIEnv *env_id; /* env where this event occurred */ union { struct { char *class_name; /* class name */ char *source_name; /* name of source file */ jint num_interfaces; /* number of interfaces implemented */ jint num_methods; /* number of methods in the class */ JVMPI_Method *methods; /* methods */ jint num_static_fields; /* number of static fields */ JVMPI_Field *statics; /* static fields */ jint num_instance_fields; /* number of instance fields */ JVMPI_Field *instances; /* instance fields */ jobjectID class_id; /* id of the class object */ } class_load; struct { jobjectID class_id; /* id of the class object */ } class_unload; ... /* Refer to the section on JVMPI events for a full listing */ } u; } JVMPI_Event;
The JVMPI refers to entities in the Java virtual machine as various kinds of IDs. Threads, classes, methods, objects, heap arenas and JNI global references all have unique IDs.
Each ID has a defining event and an undefining event. A defining event provides the information related to an ID. For example, the defining event for a thread ID contains, among other entries, the name of the thread.
An ID is valid until its undefining event arrives. An undefining event invalidates the ID, whose value may be reused later as a different kind of ID. The value of a thread ID, for example, may be redefined as a method ID after the thread ends.
ID | data type | defining event | undefining event |
---|---|---|---|
thread ID | JNIEnv * | thread start | thread end |
object ID | jobjectID | object alloc | object free, object move, and arena delete |
class ID | jobjectID | class load | class unload and object move |
method ID | jmethodID | defining class load | defining class unload |
arena ID | jint | arena new | arena delete |
JNI global ref ID | jobject | global ref alloc | global ref free |
Assuming the defining events are enabled during the profiler initialization, the profiler agent is guaranteed to be notified of an entity's creation through a defining event, before the entity appears in other JVMPI events.
If the defining events are not enabled, the profiler agent may receive an unknown ID. In that case the profiler agent may request the corresponding defining event to be sent on demand by issuing a RequestEvent call.
IDs representing objects have type jobjectID. A class is represented by the object ID of the correspondingjava.lang.Classobject. Therefore, class IDs are also of typejobjectID.
AjobjectIDis defined by an object alloc event, and remains valid in the arena in which the object is allocated until one of its undefining events arrive:
When an object free or arena delete event invalidates an object ID, the object is known as being garbage collected.
Typically, the profiler agent maintains a mapping betweenjobjectIDs and its internal representation of object identities, and updates the mapping in response to the defining and undefining events for JVMPI object IDs.
Since object IDs may be invalidated during GC, the VM issues all events that containjobjectIDentries with GC disabled. In addition, the profiling agent must disable GC when it is directly manipulating anyjobjectIDdata types. Otherwise the GC may invalidate ajobjectIDwhile it is being manipulated in the agent code. The profiler agent must make sure that GC is disabled when it calls a JVMPI function that either takes ajobjectIDargument or returns ajobjectIDresult. If the function call is inside an event handler where GC is already disabled, then the profiler agent need not explicitly disable the GC again.
A thread may be identified either by itsJNIEnvinterface pointer or by the object ID of the correspondingjava.lang.Threadobject. TheJNIEnvpointer is valid between thread start and thread end events, and remains constant during the lifetime of a thread. Thejava.lang.Threadobject ID, on the other hand, could remain valid after the thread ends, until it is garbage collected. The profiler agent can convert aJNIEnvpointer to the corresponding thread object ID by calling the GetThreadObject function.
The JVMPI is used by the profiler agent that runs in the same process as the Java virtual machine. Programmers who write the agent must be careful in dealing with threading and locking issues in order to prevent data corruption and deadlocks.
Events are sent in the same thread where they are generated. For example, a class loading event is sent in the same thread in which the class is loaded. Multiple events may arrive concurrently in different threads. The agent program must therefore provide the necessary synchronization in order to avoid data corruption caused by multiple threads updating the same data structure at the same time.
In some cases, synchronizing on certain frequent events (such as method entry and method exit) may impose unacceptable overhead to program execution. Agents may utilize the thread-local storage support provided by the JVMPI to record profiling data without having to contend for global locks, and only merge the thread-local data into global profiles at selected intervals. The JVMPI supplies the agent with a pointer-size thread-local storage. Following is a simple example that illustrates how a profiler agent may take advantage of this feature. Suppose we need to write a profiler agent that counts the number of methods executed in each thread. The agent installs event handlers for thread start, method entry, and thread end events:
/* thread start event handler * sets up the storage for thread-local method invocation counter */ void ThreadStartHandler(JNIEnv *thread_id) { int *p_ctr = (int *)malloc(sizeof(int)); CALL(SetThreadLocalStorage)(thread_id, p_ctr); } /* method enter event handler * increments thread local method invocation counter */ void MethodEntryHandler(jmethodID method_id, JNIEnv *thread_id) { int *p_ctr = (int *)CALL(GetThreadLocalStorage)(thread_id); (*p_ctr)++; } /* thread end handler * prints the number of methods executed */ void ThreadEndHandler(JNIEnv *thread_id) { int *p_ctr = (int *)CALL(GetThreadLocalStorage)(thread_id); fprintf(stdout, "Thread %x executed %d methods\n", thread_id, (*p_ctr)); free(p_ctr); }
The following JVMPI functions can cause event notification to be sent synchronously in the same thread during the function execution:
TheRequestEventfunction supplies the JVMPI event explicitly requested by the profiler agent. TheCreateSystemThreadfunction causes thread object allocation and thread start events to be issued. TheRunGCfunction causes GC-related events to be generated.
When a profiling agent is loaded into the Java virtual machine, the process can either be in one of three modes: multi-threaded mode with GC enabled, multi-threaded mode with GC disabled, and the thread suspended mode. Different JVMPI events are issued in different modes. Certain JVMPI functions change the process from one mode to another.
The profiler agent must obey the following guidelines to avoid deadlocks:
The JVMPI provides a low-level mechanism for a profiler agent to communicate with the virtual machine. The goal is to provide maximum flexiblity for the profiler agent to present the data depending on the needs of the front-end, and also to keep the processing work done by the virtual machine at a minimum. Therefore, the JVMPI does not specify a wire protocol between the profiling agent and the front-end. Instead, tools vendors design their own profiling agents that suit the needs of their front-ends.
The following issues need to be considered when designing the wire protocol in order to allow the profiler agent and front-end to reside on different machines:
For example, the HPROF profiler agent shipped with the Java 2 SDK sends the size of all IDs as the first record, and uses the standard network byte order for integer and floating-point data.
It is safe for the profiler agent to make this call only after the JVM notifies aJVMPI_EVENT_INIT_DONEand when the system is in a multi-threaded mode with GC enabled.
Arguments:
name - name of the thread. priority - thread priority; the values can be:
JVMPI_NORMAL_PRIORITY JVMPI_MAXIMUM_PRIORITY JVMPI_MINIMUM_PRIORITY f - function to be run by the thread.
Returns:
JNI_OK - success. JNI_ERR - failure.
All events are disabled when the VM starts up. Once enabled, an event stays enabled until it is explicitly disabled.
This function returnsJVMPI_NOT_AVAILABLEifevent_typeisJVMPI_EVENT_HEAP_DUMP,JVMPI_EVENT_MONITOR_DUMPorJVMPI_EVENT_OBJECT_DUMP.
Arguments:
event_type - type of event,JVMPI_EVENT_CLASS_LOADetc. arg - event specific information.
Returns:
JVMPI_SUCCESS disable succeeded. JVMPI_FAIL disable failed. JVMPI_NOT_AVAILABLE support for disabling the givenevent_typeis not available.
All events are disabled when the VM starts up. Once enabled, an event stays enabled until it is explicitly disabled.
This function returnsJVMPI_NOT_AVAILABLEifevent_typeisJVMPI_EVENT_HEAP_DUMP,JVMPI_EVENT_MONITOR_DUMPorJVMPI_EVENT_OBJECT_DUMP. The profiler agent must use the RequestEvent function to request these events.
Arguments:
event_type - type of event,JVMPI_EVENT_CLASS_LOADetc. arg - event specific argument.
Returns:
JVMPI_SUCCESS enable succeeded. JVMPI_FAIL enable failed. JVMPI_NOT_AVAILABLE support for enabling the givenevent_typeis not available.
Arguments:
trace - trace data structure to be filled by the VM. depth - depth of the call stack trace.
Returns:
time in nanoseconds
The profiler must disable GC before calling this function.
Arguments:
mid - a method ID.
Returns:
object ID of the defining class.
Arguments:
env_id - theJNIEnv *of the thread.
Returns:
the value of the thread local storage
The profiler must disable GC before calling this function.
Arguments:
env -JNIEnvpointer of the thread.
Returns:
the thread object ID.
Arguments:
env - theJNIEnv *of the thread.
Returns:
JVMPI_THREAD_RUNNABLE - thread is runnable. JVMPI_THREAD_MONITOR_WAIT - thread is waiting on a monitor. JVMPI_THREAD_CONDVAR_WAIT - thread is waiting on a condition variable. When a thread is suspended (byjava.lang.Thread.suspend,SuspendThreadorSuspendThreadList) or interrupted in any of the above states theJVMPI_THREAD_SUSPENDEDor theJVMPI_THREAD_INTERRUPTEDbit is set.
When an event is enabled byEnableEvent, the thread that generates the event is the thread in which the event is sent. When an event is requested byRequestEvent, the thread that requests the event is the thread in which the event is sent. Multiple threads may send multiple events concurrently.
If the event specific information contains ajobjectID, this function is called with GC disabled. GC is enabled after the function returns.
The space allocated for theJVMPI_Eventstructure and any event specific information is freed by the virtual machine once this function returns. The profiler agent must copy any necessary data it needs to retain into its internal buffers.
Arguments:
event - the JVMPI event sent from the VM to the profiling agent.
Arguments:
err_code - exit code
Raw monitors are similar to Java monitors. The difference is that raw monitors are not associated with Java objects.
It is not safe for the profiler agent to call this function in the thread suspended mode because this function may call arbitrary system functions such asmallocand block on an internal system library lock.
If the raw monitor is created with a name beginning with an underscore ('_'), then its monitor contention events are not sent to the profiler agent.
Arguments:
lock_name - name of raw monitor.
Returns:
a raw monitor
Raw monitors are similar to Java monitors. The difference is that raw monitors are not associated with Java objects.
It is not safe for the profiler agent to call this function in the thread suspended mode because this function may call arbitrary system functions such asfreeand block on a internal system library lock.
Arguments:
lock_id - the raw monitor to be destroyed
Raw monitors are similar to Java monitors. The difference is that raw monitors are not associated with Java objects.
It is not safe for the profiler agent to call this function in the thread suspended mode because the current thread may block on the raw monitor already acquired by one of the suspended threads.
Arguments:
lock_id - the raw monitor to be entered
Raw monitors are similar to Java monitors. The difference is that raw monitors are not associated with Java objects.
Arguments:
lock_id - the raw monitor to exit
Raw monitors are similar to Java monitors. The difference is that raw monitors are not associated with Java objects.
Arguments:
lock_id - the raw monitor to notify
Raw monitors are similar to Java monitors. The difference is that raw monitors are not associated with Java objects.
Hotspot note: if the raw monitor is not owned by the thread executingRawMonitorWait, waiting will not occur.
Arguments:
lock_id - the raw monitor to wait on ms - time to wait (in milliseconds).
This function can be called to request one-time events such asJVMPI_EVENT_HEAP_DUMP,JVMPI_EVENT_MONITOR_DUMPandJVMPI_EVENT_OBJECT_DUMP. Notification for these events cannot be controlled by the EnableEvent and DisableEvent functions.
In addition, this function can be called to request the defining events for a specific class, thread, or object. This is useful when the profiler agent needs to resolve an unknown class, method, thread, or object ID received in an event, but the corresponding defining event was disabled earlier.
Thus the profiler agent can either enable the above three events asynchronously by calling EnableEvent, or request these events synchronously by callingRequestEvent. The requested event is sent in the same thread that issued theRequestEventcall, and is sent before theRequestEventfunction returns.
TheRequestEventfunction cannot be used to request other events not listed above.
Events requested throughRequestEventwill arrive with theJVMPI_REQUESTED_EVENTbit set in itsevent_type.
Arguments:
event_type - type of event,JVMPI_EVENT_CLASS_LOADetc. arg - event specific argument.
Returns:
JVMPI_SUCCESS request succeeded. JVMPI_FAIL request failed. JVMPI_NOT_AVAILABLE support for issuing the requestedevent_typeis not available.
Note that a thread suspended by thejava.lang.Thread.suspendmethod can be resumed by the JVMPIResumeThreadfunction.
Arguments:
env - theJNIEnv *of the thread.
Arguments:
reqCount- the number of threads to resume reqList- the list of threads to resume results- the list of per-thread resume results
Returns:
The results array element for a specific thread contains zero (0) if the resume was successful and non-zero otherwise.
Arguments:
env_id - theJNIEnv *of the thread. ptr - the value to be entered into the thread-local storage.
Note that a thread suspended by the JVMPISuspendThreadfunction can be resumed by thejava.lang.Thread.resumemethod.
In the Java 2 SDK implementation, this function must be called when the GC is disabled. GC must remain disabled until all threads have been resumed.
Arguments:
env - theJNIEnv *of the thread.
In the Java 2 SDK implementation, this function must be called when the GC is disabled. GC must remain disabled until all threads have been resumed.
Arguments:
reqCount- the number of threads to suspend reqList- the list of threads to suspend results- the list of per-thread suspend results
Returns:
The results array element for a specific thread contains zero (0) if the suspend was successful and non-zero otherwise.
Arguments:
env - theJNIEnv *of the thread.
Returns:
JNI_TRUE - thread got a chance to run. JNI_FALSE - thread did not get a chance to run.
This function is experimental and may be removed from the final JVMPI specification, as its usage is very unsafe and can lead to unreliable profilers. See also note.
Arguments:
jid - the object ID to be converted.
Returns:
JNI handle
This function is experimental and may be removed from the final JVMPI specification, as its usage is very unsafe and can lead to unreliable profilers.
Arguments:
j - JNI handle.
Returns:
object ID
Usage Note:
It is not safe to invoke JNI functions in arbirtrary JVMPI event handlers. JVMPI events may be issued in virtual machine states that are not suitable for executing JNI functions. The profiler agent may only invoke JNI functions in multithreaded mode (as defined by the JVMPI specification) and must take extremely care under these circumstances to avoid race conditions, dead locks, and infinite recursions.
Note that jobjectID2jobject and jobject2jobjectID may only be invoked in GC-disabled mode (as defined by the JVMPI specification) and under this mode it not safe to call JNI functions. Thus you should never call jobjectID2jobject and then use a JNI function to process the resulting jobject in an event handler running in GC-disabled mode.
All objects residing in this arena are freed. An explicit JVMPI_EVENT_OBJECT_FREE is not sent for those objects. The profiler agent can infer all the objects currently residing in that arena by keeping track of the object allocations in the arena and all the objects moved in and out of the arena.
This event is issued in the thread suspended mode. The profiler must not make any blocking calls such as entering a monitor or allocating from the C heap (for example, viamalloc).
This event is always sent between a pair of JVMPI_EVENT_GC_START and JVMPI_EVENT_GC_FINISH events. The profiler agent should acquire all the locks need for processing this event in the event handler forJVMPI_EVENT_GC_START.
Contents:struct { jint arena_id; } delete_arena;
arena_id - ID of the arena being deleted.
Contents:struct { jint arena_id; char *arena_name; } new_arena;
arena_id - ID given to the arena. arena_name - name of the arena.
This event is issued with GC disabled. GC is re-enabled after NotifyEvent returns.
struct { char *class_name; char *source_name; jint num_interfaces; jint num_methods; JVMPI_Method *methods; jint num_static_fields; JVMPI_Field *statics; jint num_instance_fields; JVMPI_Field *instances; jobjectID class_id; } class_load;
Contents:
class_name - name of class being loaded. source_name - name of source file that defines the class. num_interfaces - number of interfaces implemented by this class. methods - methods defined in the class. num_static_fields - number of static fields defined in this class. statics - static fields defined in the class. num_instance_fields - number of instance fields defined in this class. instances - instance fields defined in the class. class_id - class object ID.
Note: class IDs are IDs of the class objects and are subject to change whenJVMPI_EVENT_OBJECT_MOVEarrives.
The profiler must allocate the space for the modified class file data buffer using the memory allocation function pointer sent in this event, because the VM is responsible for freeing the new class file data buffer.
struct { unsigned char *class_data; jint class_data_len; unsigned char *new_class_data; jint new_class_data_len; void * (*malloc_f)(unsigned int); } class_load_hook;
Contents:
class_data - pointer to the current class file data buffer. class_data_len - length of current class file data buffer. new_class_data - pointer to the instrumented class file data buffer. new_class_data_len - length of the new class file data buffer. malloc_f - pointer to a memory allocation function.
The profiler agent must setnew_class_datato point to the newly instrumented class file data buffer and setnew_class_data_lento the length of that buffer before returning from NotifyEvent. It must set bothnew_class_dataandnew_class_data_lento the old values if it chooses not to instrument this class.
This event is issued with GC disabled. GC is re-enabled after NotifyEvent returns.
struct { jobjectID class_id; } class_unload;
Contents:
class_id - class being unloaded.
struct { jmethodID method_id; void *code_addr; jint code_size; jint lineno_table_size; JVMPI_Lineno *lineno_table; } compiled_method_load;
Contents:
method_id - method being compiled and loaded. code_addr - address where compiled method code is loaded. code_size - size of compiled code. lineno_table_size - size of line number table. lineno_table - table mapping offset from beginning of method to the src file line number.
struct { jmethodID method_id; } compiled_method_unload;
Contents:
method_id - compiled method being unloaded.
There is no event specific information.
There is no event specific information.
The event-specific data contains Java heap statistics.
Contents:struct { jlong used_objects; jlong used_object_space; jlong total_object_space; } gc_info;
used_objects - number of used objects on the heap. used_object_space - amount of space used by the objects (in bytes). total_object_space - total amount of object space (in bytes).
There is no event specific information.
The dump level values can be one of the following:
If a NULL value is passed, then the dump level is set toJVMPI_DUMP_LEVEL_2.
This event is issued with GC disabled. GC is re-enabled after NotifyEvent returns.
The event-specific data contains a snapshot of all live objects in the Java heap.
Contents:struct { int dump_level; char *begin; char *end; jint num_traces; JVMPI_CallTrace *traces; } heap_dump;
dump_level - the dump level specified in RequestEvent begin - beginning of the heap dump end - end of the heap dump num_traces - number of stack traces in which the GC roots reside, 0 for JVMPI_DUMP_LEVEL_0 traces - the stack traces in which the GC roots reside
The format of the heap dump betweenbeginandenddepends on the level of information requested. The formats are described in detail in the JVMPI Dump Formats section.
This event is issued with GC disabled. GC is re-enabled after NotifyEvent returns.
Contents:struct { jobjectID obj_id; jobject ref_id; } jni_globalref_alloc;
obj_id - object ID referred to by the global reference. ref_id - JNI global reference.
Contents:struct { jobject ref_id; } jni_globalref_free;
ref_id - JNI global reference.
This event is issued with GC disabled. GC is re-enabled after NotifyEvent returns.
Contents:struct { jobjectID obj_id; jobject ref_id; } jni_globalref_alloc;
obj_id - object ID referred to by the weak global reference. ref_id - JNI weak global reference.
Contents:struct { jobject ref_id; } jni_globalref_free;
ref_id - JNI weak global reference.
There is no event specific data.
There is no event specific data.
struct { jmethodID method_id; } method;
Contents:
method_id - the method being entered.
This event is issued with GC disabled. GC is re-enabled after NotifyEvent returns.
struct { jmethodID method_id; jobjectID obj_id; } method_entry2;
Contents:
method_id - the method being entered. obj_id - the target object,NULLfor static methods.
struct { jmethodID method_id; } method;
Contents:
method_id - the method being entered.
This event is issued with GC disabled. GC is re-enabled after NotifyEvent returns.
Contents:struct { jobjectID object; } monitor;
object - object ID associated with the monitor
This event is issued with GC disabled. GC is re-enabled after NotifyEvent returns.
Contents:struct { jobjectID object; } monitor;
object - object ID associated with the monitor
This event is issued with GC disabled. GC is re-enabled after NotifyEvent returns.
Contents:struct { jobjectID object; } monitor;
object - object ID associated with the monitor
The event-specific data contains a snapshot of all the threads and monitors in the VM.
This event is issued with GC disabled. GC is re-enabled after NotifyEvent returns.
Contents:struct { char *begin; char *end; jint num_traces; JVMPI_CallTrace *traces; jint *threads_status; } monitor_dump;
begin - start of the monitor dump buffer. end - end of the dump buffer num_traces - number of thread traces. traces - traces of all threads. thread_status - status of all threads.
The format of the monitor dump buffer is described in detail in the JVMPI Dump Formats section.
This event is issued with GC disabled. GC is re-enabled after NotifyEvent returns.
Contents:struct { jobjectID object; jlong timeout; } monitor_wait;
object - ID of object on which the current thread is going to wait.
(NULLindicates the thread is inThread.sleep.) timeout - the number of milliseconds the thread will wait. (0 indicates waiting forever.)
This event is issued with GC disabled. GC is re-enabled after NotifyEvent returns.
Contents:struct { jobjectID object; jlong timeout; } monitor_wait;
object - ID of object on which the current thread waited.
(NULLindicates the thread is inThread.sleep.) timeout - the number of milliseconds the thread waited.
This event is issued with GC disabled. GC is re-enabled after NotifyEvent returns.
struct { jint arena_id; jobjectID class_id; jint is_array; jint size; jobjectID obj_id; } obj_alloc;
Contents:
arena_id - arena where allocated. class_id - class to which this object belongs, or the array element class ifis_arrayisJVMPI_CLASS. is_array - values can be:
JVMPI_NORMAL_OBJECT normal object JVMPI_CLASS array of objects JVMPI_BOOLEAN array of booleans JVMPI_BYTE array of bytes JVMPI_CHAR array of chars JVMPI_SHORT array of shorts JVMPI_INT array of ints JVMPI_LONG array of longs JVMPI_FLOAT array of floats JVMPI_DOUBLE array of doubles size - size in number of bytes. obj_id - unique object ID.
The profiler agent should request this event with GC disabled.
The event-specific data contains a snapshot of the object.
Contents:struct { jint data_len; char *data; } object_dump;
data_len - length of the object dump buffer data - beginning of the object dump
The format of the object dump buffer is described in detail in the JVMPI Dump Formats section.
This event is issued in the thread suspended mode. The profiler must not make any blocking calls such as entering a monitor or allocating from the C heap (for example, viamalloc).
This event is always sent between a pair of JVMPI_EVENT_GC_START and JVMPI_EVENT_GC_FINISH events. The profiler agent should acquire all the locks need for processing this event in the event handler forJVMPI_EVENT_GC_START.
struct { jobjectID obj_id; } obj_free;
Contents:
obj_id - object being freed.
This event is issued in the thread suspended mode. The profiler must not make any blocking calls such as entering a monitor or allocating from the C heap (for example, viamalloc).
This event is always sent between a pair of JVMPI_EVENT_GC_START and JVMPI_EVENT_GC_FINISH events. The profiler agent should acquire all the locks need for processing this event in the event handler forJVMPI_EVENT_GC_START.
struct { jint arena_id; jobjectID obj_id; jint new_arena_id; jobjectID new_obj_id; } obj_move;
Contents:
arena_id - current arena. obj_id - current object ID. new_arena_id - new arena. new_obj_id - new object ID.
Contents:struct { char *name; JVMPI_RawMonitor id; } raw_monitor;
name - name of the raw monitor id - ID of the raw monitor
Contents:struct { char *name; JVMPI_RawMonitor id; } raw_monitor;
name - name of the raw monitor id - ID of the raw monitor
Contents:struct { char *name; JVMPI_RawMonitor id; } raw_monitor;
name - name of the raw monitor id - ID of the raw monitor
Theenv_idfield of theJVMPI_Eventreceived in this event notification is theJNIEnvinterface pointer of the thread that ended.
This event is issued with GC disabled. GC is re-enabled after NotifyEvent returns.
struct { char *thread_name; char *group_name; char *parent_name; jobjectID thread_id; JNIEnv *thread_env_id; } thread_start;
Contents:
Threads are associated with aJNIEnvpointer and a thread object ID. The JVMPI uses theJNIEnvpointer as the thread ID.
thread_name - name of thread being started. group_name - group to which the thread belongs. parent_name - name of parent. thread_id - thread object ID. thread_env_id -JNIEnv *of the thread.
This thread is issued only by interpreter, and not by compiled code.
struct { jmethodID method_id; jint offset; union { struct { jboolean is_true; } if_info; struct { jint key; jint low; jint hi; } tableswitch_info; struct { jint chosen_pair_index; /* actually chosen pair index (0-based) */ jboolean is_default; /* whether default branch is taken */ } lookupswitch_info; } u; } instruction;
Contents:
method_id - id of method that executes the instruction offset - instruction offset in the method's bytecode is_true - whether true or false branch is taken in an if-bytecode key - top stack value used as an index intableswitch low - min value of the index intableswitch hi - max value of the index intableswitch chosen_pair_index - actually chosen pair index (0-based) inlookupswitch is_default - whether default branch is taken inlookupswitch
Hotspot note: must run with flag-XX:+EnableJVMPIInstructionStartEvent, otherwise no events will be sent.
u1: | 1 byte | ||||||||||||||||||||
u2: | 2 bytes | ||||||||||||||||||||
u4: | 4 bytes | ||||||||||||||||||||
u8: | 8 bytes | ||||||||||||||||||||
ty: | u1 where: | ||||||||||||||||||||
|
|
||||||||||||||||||||
vl: | values, exact size depends on the type of value: | ||||||||||||||||||||
|
|
The heap dump format depends on the level of information requested.
JVMPI_DUMP_LEVEL_0:
The dump consists of a sequence of records of the following format:
ty type of object jobjectID object
JVMPI_DUMP_LEVEL_1:
The dump format is the same as that ofJVMPI_DUMP_LEVEL_2, except that the following values are excluded from the dump: primitive fields in object instance dumps, primitive static fields in class dumps, and primitive array elements.
JVMPI_DUMP_LEVEL_2:
The dump consists of a sequence of records, where each record includes an 8-bit record type followed by data whose format is specific to each record type.
Record type Record data JVMPI_GC_ROOT_UNKNOWN
(unknown root)
jobjectID object JVMPI_GC_ROOT_JNI_GLOBAL
(JNI global ref root)
jobjectID object jobject JNI global reference JVMPI_GC_ROOT_JNI_LOCAL
(JNI local ref)
jobjectID object JNIEnv * thread u4 frame # in stack trace (-1 for empty) JVMPI_GC_ROOT_JAVA_FRAME
(Java stack frame)
jobjectID object JNIEnv * thread u4 frame # in stack trace (-1 for empty) JVMPI_GC_ROOT_NATIVE_STACK
(native stack)
jobjectID object JNIEnv * thread JVMPI_GC_ROOT_STICKY_CLASS
(system class)
jobjectID class object JVMPI_GC_ROOT_THREAD_BLOCK
(reference from thread block)
jobjectID thread object JNIEnv * thread JVMPI_GC_ROOT_MONITOR_USED
(entered monitor)
jobjectID object JVMPI_GC_CLASS_DUMP
(dump of a class object)
jobjectID class jobjectID super jobjectID class loader jobjectID signers jobjectID protection domain jobjectID class name (aStringobject, may beNULL) void * reserved u4 instance size (in bytes) [jobjectID]* interfaces u2 size of constant pool [u2, constant pool index, ty, type, vl]* value [vl]* static field values JVMPI_GC_INSTANCE_DUMP
(dump of a normal object)
jobjectID object jobjectID class u4 number of bytes that follow [vl]* instance field values (class, followed by super, super's super ...) JVMPI_GC_OBJ_ARRAY_DUMP
(dump of an object array)
jobjectID array object u4 number of elements jobjectID element class ID (may beNULLin the Java 2 SDK) [jobjectID]* elements JVMPI_GC_PRIM_ARRAY_DUMP
(dump of a primitive array)
jobjectID array object u4 number of elements ty element type [vl]* elements
The dump buffer consists of a single record which includes an 8-bit record type, followed by data specific to the record type. The record type can be one of the following:
The format of the data for each record type is the same as described above in the heap dump format section. The level of information is the same asJVMPI_DUMP_LEVEL_2, with all of the following values included: primitive fields in object instance dumps, primitive static fields in class dumps, and primitive arrays elements.
The dump buffer consists of a sequence of records, where each record includes an 8-bit record type followed by data whose format is specific to each record type.
Record type Record data JVMPI_MONITOR_JAVA
(Java monitor)
jobjectID object ID JNIEnv * owner thread u4 entry count u4 number of threads waiting to enter [JNIEnv *]* threads waiting to enter u4 number of threads waiting to be notified [JNIEnv *]* threads waiting to be notified JVMPI_MONITOR_RAW
(Raw monitor)
char * raw monitor name JVMPI_RawMonitor raw monitor ID JNIEnv * owner thread u4 entry count u4 number of threads waiting to enter [JNIEnv *]* threads waiting to enter u4 number of threads waiting to be notified [JNIEnv *]* threads waiting to be notified
Characters are encoded using the UTF-8 encoding as documented in the Java virtual machine specification.
An opaque pointer representing an object ID.
struct _jobjectID; typedef struct _jobjectID * jobjectID;
A method being executed.
Fields:typedef struct { jint lineno; jmethodID method_id; } JVMPI_CallFrame;
line number - line number in the source file. method_id - method being executed.
Fields:typedef struct { JNIEnv *env_id; jint num_frames; JVMPI_CallFrame *frames; } JVMPI_CallTrace;
env_id - ID of thread which executed this trace. num_frames - number of frames in the trace. frames -the JVMPI_CallFrames that make up this trace. Callee followed by callers.
Fields:typedef struct { char *field_name; char *field_signature; } JVMPI_Field;
field_name - name of field field_signature - signature of field
Additional info for requesting heap dumps.
Fields:typedef struct { jint heap_dump_level; } JVMPI_HeapDumpArg;
heap_dump_level - level of heap dump information, values can be:
JVMPI_DUMP_LEVEL_0 JVMPI_DUMP_LEVEL_1 JVMPI_DUMP_LEVEL_2
Fields:typedef struct { jint offset; jint lineno; } JVMPI_Lineno;
offset - offset from beginning of method lineno - lineno from beginning of source file
Fields:typedef struct { char *method_name; char *method_signature; jint start_lineno; jint end_lineno; jmethodID method_id; } JVMPI_Method;
method_name - name of method method_signature - signature of method start_lineno - start line number in the source file end_lineno - end line number in the source file method_id - ID given to this method
An opaque pointer representing a raw monitor.
struct _JVMPI_RawMonitor; typedef struct _JVMPI_RawMonitor * JVMPI_RawMonitor;
HPROF is a simple profiler agent shipped with the Java 2 SDK. It is a dynamically-linked library that interacts with the JVMPI and writes out profiling information either to a file or to a socket in ascii or binary format. This information can be further processed by a profiler front-end tool.
It is capable of presenting CPU usage, heap allocation statistics and monitor contention profiles. In addition it can also report complete heap dumps and states of all the monitors and threads in the Java virtual machine.
HPROF can be invoked by:
java -Xrunhprof ToBeProfiledClass
Depending on the type of profiling requested, HPROF instructs the virtual machine to send it the relevant JVMPI events and processes the event data into profiling information. For example, the following command obtains the heap allocation profile:
java -Xrunhprof:heap=sites ToBeProfiledClass
Following is the complete list of options that can passed to hprof :