Java Virtual Machine Debug Interface Reference
Contents
Introduction
Using JVMDI Functions
Errors
Handling Events
Starting a VM with a JVMDI ClientIntroduction
The Java Virtual Machine Debug Interface (JVMDI) is a programming interface used by debuggers and other programming tools. It provides a way both to inspect the state and to control the execution of applications running in the Java Virtual Machine.JVMDI is a two-way interface. The JVMDI client can be notified of interesting occurrences through events. The JVMDI can query and control the application through many different functions, either in response to events or independent of them.
JVMDI clients run in the same virtual machine as the application being debugged and access JVMDI through a native interface. The native, in-process interface allows maximal control with minimal intrusion on the part of a debugging tool. Typically, JVMDI clients are relatively compact. They can be controlled by a separate process which implements the bulk of a debugger's function without interfering with the target application's normal execution.
JVMDI is the lowest layer within the Java Platform Debugger Architecture. This architecture also contains higher-level, out-of-process debugger interfaces. The higher-level interfaces are more appropriate than JVMDI for most debugging tools. For more information on the Java Platform Debugger Architecture, see the Java Platform Debugger Architecture documentation for this release and the Java Platform Debugger Architecture website.
Using JVMDI Functions
For function and constant definitions, add
#include <jvmdi.h>to your source code.
Like Java Native Interface (JNI) functions, JVMDI functions are accessed through a function table. The JVMDI function table can be obtained through the JNI GetEnv function. For example, the following code obtains the function table for version 1 of the JVMDI.
JVMDI_Interface_1 *jvmdi; ... (*jvm)->GetEnv(jvm, &jvmdi, JVMDI_VERSION_1);
JVMDI functions always return a jvmdiError value indicating return status. Some functions can return additional values through pointers provided by the calling function. In some cases, JVMDI functions allocate memory that your program must explicitly deallocate. This is indicated in the individual JVMDI function descriptions. Empty lists, arrays, sequences, etc are returned as allocated zero length arrays (not as NULL).
JVMDI functions identify objects with JNI references. References passed to JVMDI functions can be either global or local, but they must be strong references. All references returned by JVMDI functions are strong, global references.
In the event that the JVMDI function encounters an error (any return value other than JVMDI_ERROR_NONE) the values of memory referenced by argument pointers is undefined, but no memory will have been allocated and no global references will have been allocated.
JVMDI extends the data types defined by JNI with the following: jthread and jthreadGroup are subtypes of jobject, representing the corresponding objects; jframeID is a pointer type representing a single stack frame of a suspended or current thread (it is invalid upon the resumption of the thread); jlocation is a 64 bit unsigned value, representing a monotonically increasing executable position within a method; jvmdiError is a jint, discussed above.
JVMDI functions fall into these categories:
- Memory Management
- Thread Execution Functions
- Thread Groups
- Stack Frame Access
- Local Variable Access
- Breakpoints
- Watched Fields
- Class Information
- Object Information
- Field Information
- Method Information
- Raw Monitor Support
- Events
- Miscellaneous Functions
Memory Management
Many JVMDI functions require memory allocation. By default, memory comes from platform-specific allocation functions, such as a malloc(). A system built on JVMDI can provide its own memory allocation scheme. This might be useful, for example, to allocate memory in advance, so a debugger can continue to function in low-memory situations. Also, replacing the default memory allocation functions with debugger-specific functions can reduce the potential for deadlock on systems where malloc cannot be entered by a debugger thread while an application thread is suspended while executing inside a memory management function.
Set Allocation Hooks
jvmdiError SetAllocationHooks(JVMDI_AllocHook ahook, JVMDI_DeallocHook dhook)
Set the functions which will perform allocation and deallocation. The hook functions are defined as follows.
typedef jvmdiError (*JVMDI_AllocHook)(jlong size, jbyte** memPtr) typedef jvmdiError (*JVMDI_DeallocHook)(jbyte* buffer)
JVMDI will call ahook to allocate memory, dhook to deallocate memory. This overrides JVMDI's default memory allocator. To restore the default allocator, call SetAllocationHooks with ahook and dhook set to NULL.
The ahook function should look in size for the number of bytes to allocate and return them via memPtr. The function should return JVMDI_ERROR_NULL_POINTER if passed null pointers, JVMDI_ERROR_OUT_OF_MEMORY if it cannot honor a memory request, and JVMDI_ERROR_NONE otherwise.
The dhook function should look in buffer for the memory to be deallocated. The function should return JVMDI_ERROR_NULL_POINTER if passed null pointers, JVMDI_ERROR_NONE otherwise.
Parameters:
- ahook
- the function to use for memory allocation, or NULL to revert to the default allocator.
- dhook
- the function to use for memory deallocation, or NULL to revert to the default deallocator.
SetAllocationHooks always returns JVMDI_ERROR_NONE.
Allocate Memory
jvmdiError Allocate(jlong size, jbyte** memPtr)
Allocate an area of memory through the JVMDI allocator. The allocated memory should be freed with Deallocate.
Parameters:
- size
- the number of bytes to allocate.
- memPtr
- on return, a pointer to the beginning of the memory allocated by the allocator specified in SetAllocationHooks.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
Deallocate Memory
jvmdiError Deallocate(jbyte* mem)
Deallocate mem using the JVMDI allocator. This function should be used to deallocate any memory allocated and returned by a JVMDI function or any memory allocated with Allocate.
Parameters:
- mem
- a pointer to the beginning of the allocated memory.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
Thread Execution Functions
Get Thread Status
jvmdiError GetThreadStatus(jthread thread, jint *threadStatusPtr, jint *suspendStatusPtr)
Get status information for a thread.
Parameters:
This function returns either a universal error or one of the following errors:
- thread
- the thread to query
- threadStatusPtr
- on return, points to the current status of the thread. If the thread is suspended, the returned status refers to the thread status before suspension. The thread status is one of the following values.
- JVMDI_THREAD_STATUS_UNKNOWN
- Status unknown.
- JVMDI_THREAD_STATUS_ZOMBIE
- Thread has completed execution.
- JVMDI_THREAD_STATUS_RUNNING
- Thread is runnable.
- JVMDI_THREAD_STATUS_SLEEPING
- Thread sleeping. (Thread.sleep() has been called.)
- JVMDI_THREAD_STATUS_MONITOR
- Thread is waiting to enter a synchronization block.
- JVMDI_THREAD_STATUS_WAIT
- Thread waiting. (Object.wait() has been called.)
- suspendStatusPtr
- on return, points to information on suspension. The suspend status is a combination of zero or more of the following bit flags.
- JVMDI_SUSPEND_STATUS_SUSPENDED
- Thread suspended. (java.lang.Thread.suspend() or SuspendThread has been called.)
- JVMDI_SUSPEND_STATUS_BREAK
- Thread has hit a breakpoint. This bit is only valid if the thread is the current thread or the thread is suspended.
- JVMDI_ERROR_INVALID_THREAD
- thread was invalid.
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
Get All Threads
jvmdiError GetAllThreads(jint *threadsCountPtr, jthread **threadsPtr)
Get all running threads known to the virtual machine. Native threads which are not attached to the VM are not included in the returned list.
Parameters:
This function returns either a universal error or one of the following errors:
- threadsCountPtr
- on return, points to the number of running threads.
- threadsPtr
- on return, points to an array of references, one for each running thread. Threads in the array are JNI global references and must be explicitly freed with the JNI function DeleteGlobalRef. The returned thread array should be freed with Deallocate.
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
Suspend Thread
jvmdiError SuspendThread(jthread thread)
Suspend the specified thread. If the calling thread is specified, this function will not return until some other thread calls ResumeThread.
Parameters:
- thread
- the thread to suspend
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_INVALID_THREAD
- thread was invalid.
- JVMDI_ERROR_THREAD_SUSPENDED
- Thread already suspended.
Resume Thread
jvmdiError ResumeThread(jthread thread)
Resume a suspended thread. Any thread suspended through SuspendThread will resume execution.
Parameters:
- thread
- the thread to resume
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_INVALID_THREAD
- thread was invalid.
- JVMDI_ERROR_THREAD_NOT_SUSPENDED
- Thread was not suspended.
- JVMDI_ERROR_INVALID_TYPESTATE
- The state of the thread has been modified, and is now inconsistent.
Stop Thread
jvmdiError StopThread(jthread thread, jobject exception)
Send the specified asynchronous exception to the specified thread (similar to java.lang.Thread.stop). Normally, this function is used to kill the specified thread with an instance of the exception ThreadDeath.
Parameters:
- thread
- the thread to stop
- exception
- the asynchronous exception object
The function returns one of the following error code:
- JVMDI_ERROR_INVALID_THREAD
Interrupt Thread
jvmdiError InterruptThread(jthread thread)
Interrupt the specified thread (similar to java.lang.Thread.interrupt).
Parameters:
- thread
- the thread to interrupt
The function returns one of the following error code:
- JVMDI_ERROR_INVALID_THREAD
Get Thread Info
typedef struct { char *name; /* Name in UTF-8 */ jint priority; jboolean is_daemon; jthreadGroup thread_group; jobject context_class_loader; } JVMDI_thread_info; jvmdiError GetThreadInfo(jthread thread, JVMDI_thread_info *infoPtr)
Get thread information. The fields of the JVMDI_thread_info structure are filled in with details of the specified thread.
Parameters:
- thread
- the thread to query
- infoPtr
- on return, filled with information describing the specified thread. Returned objects (thread group and context class loader) are global references and must be explicitly freed with the JNI function DeleteGlobalRef. The returned thread name string should be freed with Deallocate
For JDK 1.1 implementations which don't recognize context class loaders, the context_class_loader field should be NULL.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_INVALID_THREAD
- thread was invalid.
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
Get Owned Monitor Info
typedef struct { jint owned_monitor_count; jobject *owned_monitors; } JVMDI_owned_monitor_info; jvmdiError GetOwnedMonitorInfo(jthread thread, JVMDI_owned_monitor_info *infoPtr)Get information about the monitors owned by the specified thread. The fields of the JVMDI_owned_monitor_info structure are filled in with details of the owned monitors. If this function is called for a thread different than the current thread, the specified thread must be suspended.
This is an optional feature which may not be implemented for all virtual machines. Use GetCapabilities to determine whether this and other features are supported in a particular virtual machine.
Parameters:
- thread
- the thread to query
- infoPtr
- on return, filled with owned monitor information. Returned objects (array of owned monitors) are global references and must be explicitly freed with the JNI function DeleteGlobalRef. The owned_monitors buffer containing the array should be freed with Deallocate
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_INVALID_THREAD
- thread was invalid.
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_THREAD_NOT_SUSPENDED
- thread must be suspended before calling.
- JVMDI_ERROR_NOT_IMPLEMENTED
- Optional feature not present in this VM.
Get Current Contended Monitor
jvmdiError GetCurrentContendedMonitor(jthread thread, jobject *monitorPtr)Get the object, if any, whose monitor the specified thread is waiting to enter or waiting to regain through java.lang.Object.wait. If this function is called for a thread different than the current thread, the specified thread must be suspended.
This is an optional feature which may not be implemented for all virtual machines. Use GetCapabilities to determine whether this and other features are supported in a particular virtual machine.
Parameters:
- thread
- the thread to query
- monitorPtr
- on return, filled with the current contended monitor, or NULL if there is none. The contended monitor object is a global reference and must be explicitly freed with the JNI function DeleteGlobalRef.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_INVALID_THREAD
- thread was invalid.
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_THREAD_NOT_SUSPENDED
- thread must be suspended before calling.
- JVMDI_ERROR_NOT_IMPLEMENTED
- Optional feature not present in this VM.
Run Debug Thread
typedef void (*JVMDI_StartFunction)(void *); jvmdiError RunDebugThread(jthread thread, JVMDI_StartFunction proc, void *arg, int priority);Starts the execution of a debugger thread. with the specified native function. The start function is given the single argument, arg, and the specified priority. This function allows the creation of debugger threads for handling communication with another process or for handling events without the need to load a special subclass of java.lang.Thread or implementor of java.lang.Runnable. Instead, the created thread can completely native. However, the created thread does require a newly created instance of java.lang.Thread (referenced by the argument thread) to which it will be associated. The thread object can be created with JNI calls, but it is recommended that all such calls to Java programming language code be done during debugger initialization to avoid any interaction with the application being debugged.
The new thread is started as a daemon thread.
Upon execution of proc, the new thread will be attached to the VM.
Parameters:
- thread
- the thread to run
- proc
- the start function
- arg
- the argument to the start function
- priority
- the priority of the started thread. Any thread priority allowed by java.lang.Thread.setPriority can be used including
- JVMDI_THREAD_MIN_PRIORITY
- JVMDI_THREAD_NORM_PRIORITY
- JVMDI_THREAD_MAX_PRIORITY
This function returns one of the following error codes:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_THREAD
- thread was invalid.
- JVMDI_ERROR_INVALID_PRIORITY
Thread Groups
Get Top Thread Groups
jvmdiError GetTopThreadGroups(jint *groupCountPtr, jthreadGroup **groupsPtr)Return all top-level (parentless) thread groups in the VM.
Parameters:
- groupCountPtr
- on return, points to the number of top-level thread groups
- groupsPtr
- on return, refers to a pointer to the top-level thread group array. Returned group array contains global references which must be explicitly freed with the JNI function DeleteGlobalRef. The group array array buffer should be freed with Deallocate
This function returns one of the following error codes:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
Get Thread Group Info
typedef struct { jthreadGroup parent; char *name; /* Name in UTF-8 */ jint max_priority; jboolean is_daemon; } JVMDI_thread_group_info; jvmdiError GetThreadGroupInfo(jthreadGroup group, JVMDI_thread_group_info *infoPtr)Get information about the thread group. The fields of the JVMDI_thread_group_info structure are filled in with details of the specified thread group.
Parameters:
- group
- the thread group to query
- infoPtr
- on return, filled with information describing the specified thread group. The returned thread group parent is a global references and must be explicitly freed with the JNI function DeleteGlobalRef. The returned thread group name string should be freed with Deallocate
This function returns one of the following error codes:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_THREAD_GROUP
Get Thread Group Children
Get the threads and thread groups created within the given thread group.jvmdiError GetThreadGroupChildren(jthreadGroup group, jint *threadCountPtr, jthread **threadsPtr, jint *groupCountPtr, jthreadGroup **groupsPtr)Parameters:
- group
- the group to query.
- threadCountPtr
- on return, points to the number of owned threads
- threadsPtr
- on return, refers to a pointer to the owned thread array. Returned thread array contains global references which must be explicitly freed with the JNI function DeleteGlobalRef. The thread array buffer should be freed with Deallocate
- groupCountPtr
- on return, points to the number of child thread groups
- groupsPtr
- on return, refers to a pointer to the child thread group array. Returned group array contains global references which must be explicitly freed with the JNI function DeleteGlobalRef. The group array array buffer should be freed with Deallocate
This function returns one of the following error codes:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_THREAD_GROUP
Stack Frame Access
Get Thread's Frame Count
jvmdiError GetFrameCount(jthread thread, jint *countPtr)Get the number of frames currently in the specified thread's call stack.
If this function is called for a thread different than the current thread, the specified thread must be suspended.
Parameters:
This function returns either a universal error or one of the following errors:
- thread
- The thread to query
- countPtr
- on return, points to the number of frames in the call stack.
- JVMDI_ERROR_INVALID_THREAD
- thread was invalid.
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_THREAD_NOT_SUSPENDED
- Thread was not suspended.
Get Thread's Current Frame
jvmdiError GetCurrentFrame(jthread thread, jframeID *framePtr)Get the jframeID value for the current stack frame of thread and return via framePtr.
If this function is called for a thread different than the current thread, the specified thread must be suspended. The returned frame ID value remains valid only until thread continues executing. The thread must be in a Java programming language or JNI method.
Parameters:
This function returns either a universal error or one of the following errors:
- thread
- The thread to query
- framePtr
- on return, points to the frame ID for the current stack frame of this thread.
- JVMDI_ERROR_INVALID_THREAD
- thread was invalid.
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_THREAD_NOT_SUSPENDED
- Thread was not suspended.
- There are no more Java programming language or JNI frames on the call stack.
Pop Frame from Thread's Stack
jvmdiError PopFrame(jthread thread)Pop the topmost stack frame of thread's stack. Popping a frame takes you to the preceding frame. When the thread is resumed, the thread state is reset to the state immediately before the called method was invoked: the operand stack is restored (objectref if appropriate and arguments are added back), note however, that any changes to the arguments, which occurred in the called method, remain; when execution continues, the first instruction to execute will be the invoke.
Between calling PopFrame and resuming the thread the state of the stack is undefined. To pop frames beyond the first, these three steps must be repeated:
- suspend the thread via an event (step, breakpoint, ...)
- call PopFrame
- resume the thread
Locks acquired by a popped frame are released when it is popped. This applies to synchronized methods that are popped, and to any synchronized blocks within them.
Finally blocks are not executed.
Changes to global state are not addressed.
If this function is called for a thread different than the current thread, the specified thread must be suspended. The thread must be in a Java programming language or JNI method.
All frame IDs for this thread are invalidated.
No JVMDI events are generated by this function.
Native frame may not be popped.
This is an optional feature which may not be implemented for all virtual machines. Examine can_pop_frame of GetCapabilities to determine whether this feature is supported in a particular virtual machine.
Parameters:
This function returns either a universal error or one of the following errors:
- thread
- The thread whose top frame is to be popped.
- JVMDI_ERROR_INVALID_THREAD
- thread was invalid.
- JVMDI_ERROR_OPAQUE_FRAME
- frame is a native frame.
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_THREAD_NOT_SUSPENDED
- Thread was not suspended or current thread.
- There are no more Java programming language frames on the call stack.
- JVMDI_ERROR_NOT_IMPLEMENTED
- This functionality is not implemented (can_pop_frame capability is false).
Get Caller Frame
For frame, return the frame that called it via framePtr. Both called and the caller must be in a Java programming language or JNI method.jvmdiError GetCallerFrame(jframeID called, jframeID *framePtr)Parameters:
- called
- the called frame.
- framePtr
- on return, points to the frame ID for the calling frame.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_FRAMEID
- Invalid jframeID.
- The caller frame is not in a Java programming language or JNI method.
Frame Location
jvmdiError GetFrameLocation(jframeID frame, jclass *classPtr, jmethodID *methodPtr, jlocation *locationPtr)For a Java programming language frame, return the location of the instruction currently executing.
Parameters:
- frame
- the frame to query.
- classPtr
- on return, points to the class for the current location. The returned class is a JNI global reference must be explicitly freed with the JNI function DeleteGlobalRef.
- methodPtr
- on return, points to the method for the current location.
- locationPtr
- on return, points to the index of the currently executing instruction.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_OPAQUE_FRAME
- frame is not a Java programming language frame.
- JVMDI_ERROR_INVALID_FRAMEID
- frame is not a valid frame ID.
Notify Frame Pop
jvmdiError NotifyFramePop(jframeID frame);When frame is popped from the stack, generate a JVMDI_EVENT_FRAME_POP event. See Events.
Parameters:
- frame
- the frame for which the frame pop event will be generated.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_OPAQUE_FRAME
- frame is not a Java programming language frame.
- JVMDI_ERROR_INVALID_FRAMEID
- frame is not a valid frame ID.
Local Variable Access
Get Local Variable
jvmdiError GetLocalObject(jframeID frame, jint slot, jobject *valuePtr)jvmdiError GetLocalInt(jframeID frame, jint slot, jint *valuePtr)jvmdiError GetLocalLong(jframeID frame, jint slot, jlong *valuePtr)jvmdiError GetLocalFloat(jframeID frame, jint slot, jfloat *valuePtr)jvmdiError GetLocalDouble(jframeID frame, jint slot, jdouble *valuePtr)These functions are used to retrieve the value of a local variable. GetLocalInt can be used to retrieve int, char, byte, and boolean values. The variable is identified by the frame containing its value and the variable's slot number. The mapping of variables to slot numbers can be obtained with the function GetLocalVariableTable.
Parameters:
- frame
- the frame containing the variable's value.
- slot
- the variable's slot number.
- valuePtr
- on return, points to the variable's value. For GetLocalObject, the returned value is a global reference and must be explicitly freed with the JNI function DeleteGlobalRef().
The functions return one of the following error codes:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_FRAMEID
- Invalid frame.
- JVMDI_ERROR_INVALID_SLOT
- Invalid slot.
- JVMDI_ERROR_TYPE_MISMATCH
- The variable is not an appropriate type for the function used.
- JVMDI_ERROR_OPAQUE_FRAME
Set Local Variable
jvmdiError SetLocalObject(jframeID frame, jint slot, jobject value)jvmdiError SetLocalInt(jframeID frame, jint slot, jint value)jvmdiError SetLocalLong(jframeID frame, jint slot, jlong value)jvmdiError SetLocalFloat(jframeID frame, jint slot, jfloat value)jvmdiError SetLocalDouble(jframeID frame, jint slot, jdouble value)These functions are used to set the value of a local variable. SetLocalInt can be used to set int, char, byte, and boolean values. The variable is identified by the frame containing its value and the variable's slot number. The mapping of variables to slot numbers can be obtained with the function GetLocalVariableTable.
Parameters:
- frame
- the frame containing the variable's value.
- slot
- the variable's slot number.
- value
- the new value for the variable
The functions return one of the following error codes:
- JVMDI_ERROR_OPAQUE_FRAME
- Invalid pointer.
- JVMDI_ERROR_INVALID_FRAMEID
- Invalid frame.
- JVMDI_ERROR_INVALID_SLOT
- Invalid slot.
- JVMDI_ERROR_TYPE_MISMATCH
- The variable is not an appropriate type for the function used.
Breakpoints
Set a Breakpoint
jvmdiError SetBreakpoint(jclass clazz, jmethodID method, jlocation location)Set a breakpoint at the instruction indicated by clazz, method, and location. An instruction can only have one breakpoint.
Whenever the designated instruction is about to be executed, a JVMDI_EVENT_BREAKPOINT event is generated. See Events.
Parameters:
- clazz
- the class in which to set the breakpoint
- method
- the method in which to set the breakpoint
- location
- the index of the instruction at which to set the breakpoint
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_INVALID_METHODID
- Invalid method.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
- JVMDI_ERROR_INVALID_LOCATION
- Invalid location.
- JVMDI_ERROR_DUPLICATE
- The designated bytecode already has a breakpoint.
Clear a Breakpoint
jvmdiError ClearBreakpoint(jclass clazz, jmethodID method, jlocation location)Clear the breakpoint at the bytecode indicated by clazz, method, and location.
Parameters:
- clazz
- the class in which to clear the breakpoint
- method
- the method in which to clear the breakpoint
- location
- the index of the instruction at which to clear the breakpoint
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_INVALID_METHODID
- Invalid method.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
- JVMDI_ERROR_INVALID_LOCATION
- Invalid location.
- JVMDI_ERROR_NOT_FOUND
- There's no breakpoint at the designated bytecode.
Clear All Breakpoints
Clear all breakpoints in this virtual machine.jvmdiError ClearAllBreakpoints()
Watched Fields
Set a Field Access Watch
jvmdiError SetFieldAccessWatch(jclass clazz, jfieldID field)Generate a JVMDI_EVENT_FIELD_ACCESS event when the field specified by clazz and field is about to be accessed. An event will be generated for each access of the field until it is cancelled with ClearFieldAccessWatch. Field accesses from Java programming language code or from JNI are watched, fields modified by other means are not watched. Note that JVMDI users should be aware that their own field accesses will trigger the watch. A field can only have one field access watch set. Modification of a field is not considered an access - use SetFieldModificationWatch to monitor modifications.
This is an optional feature which may not be implemented for all virtual machines. Use GetCapabilities to determine whether this and other features are supported in a particular virtual machine.
Parameters:
- clazz
- the class containing the field to watch
- field
- the field to watch
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_INVALID_FIELDID
- The jfieldID specified in field is not a valid field ID.
- JVMDI_ERROR_INVALID_CLASS
- The jclass specified in clazz is no a valid class.
- JVMDI_ERROR_DUPLICATE
- The designated field is already being watched for accesses.
- JVMDI_ERROR_NOT_IMPLEMENTED
- Optional feature not present in this VM.
Clear a Field Access Watch
jvmdiError ClearFieldAccessWatch(jclass clazz, jfieldID field)Cancel a field access watch previously set by SetFieldAccessWatch, on the field specified by clazz and field.
Parameters:
- clazz
- the class containing the field to watch
- field
- the field to watch
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_INVALID_FIELDID
- The jfieldID specified in field is not a valid field ID.
- JVMDI_ERROR_INVALID_CLASS
- The jclass specified in clazz is no a valid class.
- JVMDI_ERROR_NOT_FOUND
- The designated field is not being watched for accesses.
Set a Field Modification Watch
jvmdiError SetFieldModificationWatch(jclass clazz, jfieldID field)Generate a JVMDI_EVENT_FIELD_MODIFICATION event when the field specified by clazz and field is about to be modified. An event will be generated for each modification of the field until it is cancelled with ClearFieldModificationWatch. Field modifications from Java programming language code or from JNI are watched, fields modified by other means are not watched. Note that JVMDI users should be aware that their own field modifications will trigger the watch. A field can only have one field modification watch set.
This is an optional feature which may not be implemented for all virtual machines. Use GetCapabilities to determine whether this and other features are supported in a particular virtual machine.
Parameters:
- clazz
- the class containing the field to watch
- field
- the field to watch
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_INVALID_FIELDID
- The jfieldID specified in field is not a valid field ID.
- JVMDI_ERROR_INVALID_CLASS
- The jclass specified in clazz is no a valid class.
- JVMDI_ERROR_DUPLICATE
- The designated field is already being watched for modifications.
- JVMDI_ERROR_NOT_IMPLEMENTED
- Optional feature not present in this VM.
Clear a Field Modification Watch
jvmdiError ClearFieldModificationWatch(jclass clazz, jfieldID field)Cancel a field modification watch previously set by SetFieldModificationWatch, on the field specified by clazz and field.
Parameters:
- clazz
- the class containing the field to watch
- field
- the field to watch
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_INVALID_FIELDID
- The jfieldID specified in field is not a valid field ID.
- JVMDI_ERROR_INVALID_CLASS
- The jclass specified in clazz is no a valid class.
- JVMDI_ERROR_NOT_FOUND
- The designated field is not being watched for modifications.
Class Information
Class Signature
For the class indicated by clazz, return the class signature via sigPtr. The return value is a UTF-8 string.jvmdiError GetClassSignature(jclass clazz, char **sigPtr)The returned signature for primitive classes (for example, java.lang.Integer.TYPE) is the signature of the corresponding primitive type (for example, "I").
Parameters:
- clazz
- the class to query
- sigPtr
- on return, refers to a pointer to the class's signature (UTF-8). The returned signature string should be freed with Deallocate
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
Class Status
jvmdiError GetClassStatus(jclass clazz, jint *statusPtr)Get the status of the class. Zero or more of the following bits can be set.
- JVMDI_CLASS_STATUS_VERIFIED
- Class bytecodes have been verified.
- JVMDI_CLASS_STATUS_PREPARED
- Class preparation is complete.
- JVMDI_CLASS_STATUS_INITIALIZED
- Class initialization is complete. Static initializer has been run.
- JVMDI_CLASS_STATUS_ERROR
- Error during initialization makes class unusable.
The status value for primitive classes (for example, java.lang.Integer.TYPE) and for arrays is undefined.
Parameters:
- clazz
- the class to query
- statusPtr
- on return, points to the current state of this class as one or more of flags described above.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
Source File Name
For the class indicated by clazz, return the source file name via sourceNamePtr. The returned UTF-8 string is a file name only and never contains a directory name.jvmdiError GetSourceFileName(jclass clazz, char **sourceNamePtr)For primitive classes (for example, java.lang.Integer.TYPE) and for arrays this function returns JVMDI_ERROR_ABSENT_INFORMATION.
Parameters:
- clazz
- the class to query
- sourceNamePtr
- on return, refers to a pointer to the class's source file name (UTF-8). The returned file name string should be freed with Deallocate
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
- JVMDI_ERROR_ABSENT_INFORMATION
- Class information does not include a source path. This includes the case where the class is an array class or primitive class.
Class Modifier Flags
For the class indicated by clazz, return the access flags via modifiersPtr. Access flag definitions and information about class modifiers can be found in the Java virtual machine specification.jvmdiError GetClassModifiers(jclass clazz, jint *modifiersPtr)If the class is an array class, then its public, private and protected modifiers are the same as those of its component type. For arrays of primitives, this component type is represented by one of the primitive classes (for example, java.lang.Integer.TYPE).
If the class is a primitive class, its public modifier is always true, and its protected and private modifiers are always false.
If the class is an array class or a primitive class then its final modifier is always true and its interface modifier is always false. The values of its other modifiers are not determined by this specification.
Parameters:
- clazz
- the class to query
- modifiersPtr
- on return, points to the current access flags of this class.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
Class Methods
For the class indicated by clazz, return a count of methods via methodCountPtr and a list of method IDs via methodsPtr. The method list contains constructors and static initializers as well as true methods. Only directly declared methods are returned (not inherited methods). Methods are returned in the order they occur in the class file. An empty method list is returned for array classes and primitive classes (for example, java.lang.Integer.TYPE).jvmdiError GetClassMethods(jclass clazz, jint *methodCountPtr, jmethodID **methodsPtr)Parameters:
- clazz
- the class to query
- methodCountPtr
- on return, points to the number of methods declared in this class.
- methodsPtr
- on return, points to the method ID array. The JVMDI allocator provides memory for the array. You must deallocate the array using Deallocate().
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
- JVMDI_ERROR_CLASS_NOT_PREPARED
Class Fields
For the class indicated by clazz, return a count of fields via fieldCountPtr and a list of field IDs via fieldsPtr. Only directly declared fields are returned (not inherited fields). Fields are returned in the order they occur in the class file. An empty field list is returned for array classes and primitive classes (for example, java.lang.Integer.TYPE). Use JNI to determine the length of an array.jvmdiError GetClassFields(jclass clazz, jint *fieldCountPtr, jfieldID **fieldsPtr)Parameters:
- clazz
- the class to query
- fieldCountPtr
- on return, points to the number of fields declared in this class.
- fieldsPtr
- on return, points to the field ID array. The JVMDI allocator provides memory for the array. You must deallocate it using Deallocate().
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
- JVMDI_ERROR_CLASS_NOT_PREPARED
Implemented Interfaces
Return the direct super-interfaces of this class. For a class, this function returns the interfaces declared in its implements clause. For an interface, this function returns the interfaces declared in its extends clause. An empty interface list is returned for array classes and primitive classes (for example, java.lang.Integer.TYPE).jvmdiError GetImplementedInterfaces(jclass clazz, jint *interfaceCountPtr, jclass **interfacesPtr);Parameters:
- clazz
- the class to query
- interfaceCountPtr
- on return, points to the number of interfaces.
- interfacesPtr
- on return, points to the interface array. Interfaces in the array are JNI global references and must be explicitly freed with the JNI function DeleteGlobalRef. The returned interface array should be freed with Deallocate.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
- JVMDI_ERROR_CLASS_NOT_PREPARED
Is an Interface
Determines whether a class object reference represents an interface. The jboolean result is JNI_TRUE if the "class" is actually an interface, JNI_FALSE otherwise.jvmdiError IsInterface(jclass clazz, jboolean *isInterfacePtr)Parameters:
- clazz
- the class to query
- isInterfacePtr
- on return, points to the boolean result of this function.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
Is an Array
Determines whether a class object reference represents an array. The jboolean result is JNI_TRUE if the class is an array, JNI_FALSE otherwise.jvmdiError IsArrayClass(jclass clazz, jboolean *isArrayClassPtr)Parameters:
- clazz
- the class to query
- isArrayClassPtr
- on return, points to the boolean result of this function.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
Class Loader
For the class indicated by clazz, return via classloaderPtr a reference to the class loader for the class. If the class was not created by a class loader, classloaderPtr points to NULL.jvmdiError GetClassLoader(jclass clazz, jobject *classloaderPtr)Parameters:
- clazz
- the class to query
- classloaderPtr
- on return, points to the class loader that loaded this class or interface, or NULL if there it has no class loader. The returned classloader is a JNI global reference and must be explicitly freed with the JNI function DeleteGlobalRef.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
Source Debug Extension
For the class indicated by clazz, return the debug extension via sourceDebugExtensionPtr. The returned UTF-8 string contains exactly the debug extension information present in the class file of clazz.jvmdiError GetSourceDebugExtension(jclass clazz, char **sourceDebugExtensionPtr)Parameters:
- clazz
- the class to query
- sourceDebugExtensionPtr
- on return, refers to a pointer to the class's debug extension name (UTF-8). The returned debug extension string should be freed with Deallocate
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
- JVMDI_ERROR_ABSENT_INFORMATION
- Class information does not include a debug extension.
Object Information
Object Hash Code
For the object indicated by object return via hashCodePtr a hash code that can be used in maintaining hash table of object references. This function guarantees the same hash code value for a particular object throughout its lifejvmdiError GetObjectHashCode(jobject object, jint *hashCodePtr)Parameters:
- object
- the object to query
- hashCodePtr
- on return, points to the object's hash code
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_OBJECT
- Invalid object.
Get Monitor Info
typedef struct { jthread owner; jint entry_count; jint waiter_count; jthread *waiters; } JVMDI_monitor_info; jvmdiError GetMonitorInfo(jobject object, JVMDI_monitor_info *infoPtr)Get information about the the object's monitor The fields of the JVMDI_owned_monitor_info structure are filled in with details of the monitor. Each thread that might affect the monitor state must either be suspended or must be the current thread.
This is an optional feature which may not be implemented for all virtual machines. Use GetCapabilities to determine whether this and other features are supported in a particular virtual machine.
Parameters:
- object
- the object to query
- infoPtr
- on return, filled with monitor information for the specified object. Returned objects (owner, array of waiters) are global references and must be explicitly freed with the JNI function DeleteGlobalRef. The returned waiter array buffer should be freed with Deallocate
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_INVALID_OBJECT
- thread was invalid.
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_THREAD_NOT_SUSPENDED
- thread must be suspended before calling.
- JVMDI_ERROR_NOT_IMPLEMENTED
- Optional feature not present in this VM.
Field Information
Field Name and Signature
For the field indicated by clazz and field, return the field name via namePtr and field signature via signaturePtr.jvmdiError GetFieldName(jclass clazz, jfieldID field, char **namePtr, char **signaturePtr)Parameters:
- clazz
- the class to query
- field
- the field to query
- namePtr
- on return, refers to a pointer to the UTF-8 field name. The string should be freed with Deallocate
- signaturePtr
- on return, refers to a pointer to the UTF-8 field signature. The string should be freed with Deallocate
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_FIELDID
- Invalid field.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
Field Declaring Class
For the field indicated by clazz and field return the class that defined it via declaringClassPtr. The declaring class will either be clazz. a superclass, or an implemented interface.jvmdiError GetFieldDeclaringClass(jclass clazz, jfieldID field, jclass *declaringClassPtr)Parameters:
- clazz
- the class to query
- field
- the field to query
- declaringClassPtr
- on return, points to the declaring class The returned class is a JNI global reference and must be explicitly freed with freed with the JNI function DeleteGlobalRef.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_FIELDID
- Invalid field.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
Field Modifier Flags
For the field indicated by clazz and field return the access flags via modifiersPtr. Access flag definitions and information about field modifiers can be found in the Java virtual machine specification.jvmdiError GetFieldModifiers(jclass clazz, jfieldID field, jint *modifiersPtr)Parameters:
- clazz
- the class to query
- field
- the field to query
- modifiersPtr
- on return, points to the access flags.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_FIELDID
- Invalid method.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
Is Field Synthetic
jvmdiError IsFieldSynthetic(jclass clazz, jfieldID field, jboolean *isSyntheticPtr)For the field indicated by clazz and field, return a value indicating whether the field is synthetic via isSyntheticPtr Synthetic fields are generated by the compiler but not present in the original source code.
This is an optional feature which may not be implemented for all virtual machines. Use GetCapabilities to determine whether this and other features are supported in a particular virtual machine.
Parameters:
- clazz
- the class to query
- field
- the field to query
- isSyntheticPtr
- on return, points to the boolean result of this function.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_FIELDID
- Invalid field.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
- JVMDI_ERROR_NOT_IMPLEMENTED
- Optional feature not present in this VM.
Method Information
Method Name and Signature
jvmdiError GetMethodName(jclass clazz, jmethodID method, char **namePtr, char **signaturePtr)For the method indicated by clazz and method, return the method name via namePtr and method signature via signaturePtr. The signature is a JNI signature also called a method descriptor in the Java Virtual Machine Specification; note this is different then method signature as defined in the Java Language Specification.
Parameters:
- clazz
- the class to query
- method
- the method to query
- namePtr
- on return, refers to a pointer to the UTF-8 method name. The string should be freed with Deallocate
- signaturePtr
- on return, refers to a pointer to the UTF-8 method signature. The string should be freed with Deallocate
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_METHODID
- Invalid method.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
Method Declaring Class
For the method indicated by clazz and method, return the Class that defined it via declaringClassPtr.jvmdiError GetMethodDeclaringClass(jclass clazz, jmethodID method, jclass *declaringClassPtr)Parameters:
- clazz
- the class to query
- method
- the method to query
- declaringClassPtr
- on return, points to the declaring class The returned class is a JNI global reference and must be explicitly freed with freed with the JNI function DeleteGlobalRef.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_METHODID
- Invalid method.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
Method Modifier Flags
For the method indicated by clazz and method return the access flags via modifiersPtr. Access flag definitions and information about method modifiers can be found in the Java virtual machine specification.jvmdiError GetMethodModifiers(jclass clazz, jmethodID method, jint *modifiersPtr)Parameters:
- clazz
- the class to query
- method
- the method to query
- modifiersPtr
- on return, points to the access flags.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_METHODID
- Invalid method.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
Maximum Stack
For the method indicated by clazz and method, return via maxPtr the maximum number of words that can be on the stack while the method is executing.jvmdiError GetMaxStack(jclass clazz, jmethodID method, jint *maxPtr)Parameters:
- clazz
- the class to query
- method
- the method to query
- maxPtr
- on return, points to the maximum number of stack words
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_METHODID
- Invalid method.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
Locals Slots
For the method indicated by clazz and method, return via maxPtr the number of local variable slots used by the whole method. Note that two-word arguments use two slots.jvmdiError GetMaxLocals(jclass clazz, jmethodID method, jint *maxPtr);Parameters:
- clazz
- the class to query
- method
- the method to query
- maxPtr
- on return, points to the maximum number of local slots
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_METHODID
- Invalid method.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
Argument Slots
For the method indicated by clazz and method, return via maxPtr the number of local variable slots used by the method's arguments. Note that two-word arguments use two slots.jvmdiError GetArgumentsSize(jclass clazz, jmethodID method, jint *sizePtr)Parameters:
- clazz
- the class to query
- method
- the method to query
- sizePtr
- on return, points to the number of argument slots
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_METHODID
- Invalid method.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
Source Line Numbers
For the method indicated by clazz and method, return a table of source line number entries. The size of the table is returned via entryCountPtr and the table itself is returned via tablePtr. A table entry is an instance of the following structure:jvmdiError GetLineNumberTable(jclass clazz, jmethodID method, jint *entryCountPtr, JVMDI_line_number_entry **tablePtr)typedef struct { jlocation start_location; jint line_number; } JVMDI_line_number_entry;Parameters:
- clazz
- the class to query
- method
- the method to query
- entryCountPtr
- on return, points to the number of entries in the table
- tablePtr
- on return, points to the line number table pointer. The JVMDI allocator provides space for the table. You must deallocate the table using Deallocate().
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NONE
- No error.
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_METHODID
- Invalid method.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
- JVMDI_ERROR_ABSENT_INFORMATION
- Class information does not include line numbers.
Method Location
For the method indicated by clazz and method, return the beginning and ending addresses through startLocationPtr and endLocationPtr. In a conventional byte code indexing scheme, these values are always zero and the byte code count minus one.jvmdiError GetMethodLocation(jclass clazz, jmethodID method, jlocation *startLocationPtr, jlocation *endLocationPtr)Parameters:
- clazz
- the class to query
- method
- the method to query
- startLocationPtr
- on return, points to the first location, or -1 if location information is not available.
- endLocationPtr
- on return, points to the last location, or -1 if location information is not available.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_METHODID
- Invalid method.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
- JVMDI_ERROR_ABSENT_INFORMATION
- Class information does not include method sizes.
Local Variables
For the method indicated by clazz and method, return a table of local variables. The size of the table is returned via entryCountPtr and the table itself is returned via tablePtr. A table entry has this structure:jvmdiError GetLocalVariableTable(jclass clazz, jmethodID method, jint *entryCountPtr, JVMDI_local_variable_entry **tablePtr)typedef struct { jlocation start_location; /* variable valid start_location */ jint length; /* up to start_location+length */ char *name; /* name in UTF-8 */ char *signature; /* type signature in UTF-8 */ jint slot; /* variable slot, see JVMDI_GetLocal*() */ } JVMDI_local_variable_entry;Parameters:
- clazz
- the class to query
- method
- the method to query
- entryCountPtr
- on return, points to the number of entries in the table
- tablePtr
- on return, points to the local variable table pointer. The JVMDI allocator provides space for the table. In addition, each name and signature string in the table is allocated with the JVMDI allocator. You must deallocate these buffers using Deallocate.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_METHODID
- Invalid method.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
- JVMDI_ERROR_ABSENT_INFORMATION
- Class information does not include local variable information.
Exception Handlers
For the method indicated by clazz and method, return a table of exception handlers. The size of the table is returned via entryCountPtr and the table itself is returned via tablePtr. A table entry has this structure:jvmdiError GetExceptionHandlerTable(jclass clazz, jmethodID method, jint *entryCountPtr, JVMDI_exception_handler_entry **tablePtr)typedef struct { jlocation start_location; jlocation end_location; jlocation handler_location; jclass exception; /* if null, all exceptions */ } JVMDI_exception_handler_entry;A call to this function may trigger class loading for the thrown exception classes that have not yet been loaded. It should not be called while threads are suspended.
Parameters:
- clazz
- the class to query
- method
- the method to query
- entryCountPtr
- on return, points to the number of entries in the table
- tablePtr
- on return, points to the exception handler table pointer. The JVMDI allocator provides space for the table. You must deallocate the table using Deallocate(). The classes returned in the "exception" field of JVMDI_exception_handler_entry are global references and must be explicitly freed with the JNI function Deallocate
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_METHODID
- Invalid method.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
Thrown Exceptions
For the method indicated by clazz and method, return an array of exception classes the method might throw. The number of exceptions is returned via exceptionCountPtr. The exceptions array is returned via exceptionsPtr.jvmdiError GetThrownExceptions(jclass clazz, jmethodID method, jint *exceptionCountPtr, jclass **exceptionsPtr)A call to this function may trigger class loading for the thrown exception classes that have not yet been loaded. It should not be called while threads are suspended.
Parameters:
- clazz
- the class to query
- method
- the method to query
- exceptionCountPtr
- on return, points to the number of running threads.
- exceptionsPtr
- on return, points to an array of references, one for each thrown exception. Exception classes in the array are JNI global references and must be explicitly freed with the JNI function DeleteGlobalRef. The returned exception array should be freed with Deallocate.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_METHODID
- Invalid method.
- JVMDI_ERROR_INVALID_CLASS
- Invalid class.
Get Bytecodes
For the method indicated by clazz and method, return the byte codes that implement the method. The number of bytecodes is returned via bytecodeCountPtr. The byte codes themselves are returned via bytecodesPtr.jvmdiError GetBytecodes(jclass clazz, jmethodID method, jint *bytecodeCountPtr, jbyte **bytecodesPtr)This is an optional feature which may not be implemented for all virtual machines. Use GetCapabilities to determine whether this and other features are supported in a particular virtual machine.
Parameters:
- clazz
- the class to query
- method
- the method to query
- bytecodeCountPtr
- on return, points to the length of the byte code array
- bytecodesPtr
- on return, points to the pointer to the byte code array The JVMDI memory allocator provides memory for the byte code array. You must deallocate the table using Deallocate().
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
- JVMDI_ERROR_INVALID_METHODID
- Invalid method.
- JVMDI_ERROR_NOT_IMPLEMENTED
- Optional feature not present in this VM.
Is Method Native
jvmdiError IsMethodNative(jclass clazz, jmethodID method, jboolean *isNativePtr)For the method indicated by clazz and method, return a value indicating whether the method is native via isNativePtr
Parameters:
- clazz
- the class to query
- method
- the method to query
- isNativePtr
- on return, points to the boolean result of this function.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_METHODID
- Invalid method.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
Is Method Synthetic
jvmdiError IsMethodSynthetic(jclass clazz, jmethodID method, jboolean *isSyntheticPtr)For the method indicated by clazz and method, return a value indicating whether the method is synthetic via isSyntheticPtr. Synthetic methods are generated by the compiler but not present in the original source code.
This is an optional feature which may not be implemented for all virtual machines. Use GetCapabilities to determine whether this and other features are supported in a particular virtual machine.
Parameters:
- clazz
- the class to query
- method
- the method to query
- isSyntheticPtr
- on return, points to the boolean result of this function.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
- JVMDI_ERROR_INVALID_METHODID
- Invalid method.
- JVMDI_ERROR_INVALID_CLASS
- Invalid clazz.
- JVMDI_ERROR_NOT_IMPLEMENTED
- Optional feature not present in this VM.
Raw Monitor Support
Create Raw Monitor
Create a raw monitor.jvmdiError CreateRawMonitor(char *name, JVMDI_RawMonitor *monitorPtr)Parameters:
- name
- a name in UTF-8 to identify the monitor
- monitorPtr
- on return, points to the created monitor.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
Destroy Raw Monitor
Destroy the raw monitor.jvmdiError DestroyRawMonitor(JVMDI_RawMonitor monitor)Parameters:
- monitor
- the monitor
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
Raw Monitor Enter
Gain exclusive ownership of a raw monitor.jvmdiError RawMonitorEnter(JVMDI_RawMonitor monitor)Parameters:
- monitor
- the monitor
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_INVALID_MONITOR
- Invalid monitor.
Raw Monitor Exit
Release exclusive ownership of a raw monitor.jvmdiError RawMonitorExit(JVMDI_RawMonitor monitor)Parameters:
- monitor
- the monitor
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_INVALID_MONITOR
- Invalid monitor.
Raw Monitor Wait
Wait for notification of the raw monitor.jvmdiError RawMonitorWait(JVMDI_RawMonitor monitor, jlong millis)Parameters:
- monitor
- the monitor
- millis
- the timeout, in milliseconds
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_INVALID_MONITOR
- Invalid monitor.
- JVMDI_ERROR_NOT_MONITOR_OWNER
- JVMDI_ERROR_INTERRUPT
Raw Monitor Notify
Notify a single thread waiting on the raw monitor.jvmdiError RawMonitorNotify(JVMDI_RawMonitor monitor)Parameters:
- monitor
- the monitor
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_INVALID_MONITOR
- Invalid monitor.
- JVMDI_ERROR_NOT_MONITOR_OWNER
Raw Monitor Notify All
Notify all threads waiting on the raw monitor.jvmdiError RawMonitorNotifyAll(JVMDI_RawMonitor monitor)Parameters:
- monitor
- the monitor
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_INVALID_MONITOR
- Invalid monitor.
- JVMDI_ERROR_NOT_MONITOR_OWNER
Events
Set Event Hook
Set the function to be called on every event. Details on events are described later in this document.typedef void (*JVMDI_EventHook)(JNIEnv *env , JVMDI_Event *event); jvmdiError SetEventHook(JVMDI_EventHook hook)Parameters:
- hook
- the new event hook, or NULL to remove the existing hook.
This function returns a universal error on error.
Enable/Disable Events
Control the generation of events. If mode is JVMDI_ENABLE, the event eventType is enabled; if mode is JVMDI_DISABLE, the event is disabled. If thread is NULL, the event is enabled or disabled globally; otherwise, it is enabled or disabled for a particular thread. An event is generated for a particular thread if it is enabled either at the thread or global levels.jvmdiError SetEventNotificationMode(jint mode, jint eventType, jthread thread, ...)Global and per-thread enabling of events is independent. For example, if MethodEntry is initially disabled both globally and on each thread, MethodEntry is still disabled per-thread when it is enabled globally. When an executing thread encounters a potential event condition, an event will be sent if either that event is globally enabled OR that event is enabled for the executing thread. Thus globally enabling an event applies to threads created after the call as well.
See below for information on specific events.
The following events cannot be controlled (enabled or disabled) at the thread level through this function.
- JVMDI_EVENT_VM_INIT
- JVMDI_EVENT_VM_DEATH
- JVMDI_EVENT_THREAD_START
- JVMDI_EVENT_CLASS_UNLOAD
The following event cannot be controlled (enabled or disabled) at the global level through this function.
- JVMDI_EVENT_SINGLE_STEP
Initially, no events are enabled at the thread level. All events except the following are enabled at the global level.
Set the function to be called on every event. Details on events are described later in this document.
- JVMDI_EVENT_SINGLE_STEP
- JVMDI_EVENT_EXCEPTION_CATCH
- JVMDI_EVENT_METHOD_ENTRY
- JVMDI_EVENT_METHOD_EXIT
Parameters:
- mode
- JVMDI_ENABLE or JVMDI_DISABLE
- eventType
- the event to control
- thread
- the thread to control, or NULL for all threads
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_INVALID_THREAD
- If thread is invalid or the thread has not run.
- JVMDI_ERROR_INVALID_EVENT_TYPE
- If eventType is invalid value.
- JVMDI_ERROR_ILLEGAL_ARGUMENT
- If thread argument is specified with one of the following events:
- JVMDI_EVENT_VM_INIT
- JVMDI_EVENT_VM_DEATH
- JVMDI_EVENT_THREAD_START
- JVMDI_EVENT_CLASS_UNLOAD
Miscellaneous Functions
Get Loaded Classes
jvmdiError GetLoadedClasses(jint *classCountPtr, jclass **classesPtr)Return an array of all classes loaded in the virtual machine. The number of classes in the array is returned via classCountPtr, and the array itself via classesPtr. You must deallocate the array using Deallocate().
Array classes of all types (including arrays of primitive types) are included in the returned list. Primitive classes (for example, java.lang.Integer.TYPE) are not included in this list.
Parameters:
- classCountPtr
- on return, points to the number of classes.
- classesPtr
- on return, points to an array of references, one for each class. Classes in the array are JNI global references and must be explicitly freed with the JNI function DeleteGlobalRef. The returned class array should be freed with Deallocate.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
Get Classloader Classes
jvmdiError GetClassLoaderClasses(jobject initiatingLoader, jint *classCountPtr, jclass **classesPtr)Returns an array of all classes for which this class loader has been recorded as the initiating loader. Each class in the returned array was created by this class loader, either by defining it directly or by delegation to another class loader.
For JDK 1.1 implementations which don't recognize the distinction between initiating and defining classloaders, this function should return all classes loaded in the virtual machine. The number of classes in the array is returned via classCountPtr, and the array itself via classesPtr. You must deallocate the array using Deallocate().
The initiatingLoader argument must not be null. The set of classes initiated by the system class loader is identical to the set of classes defined by that loader. This set can be determined by calling GetLoadedClasses and selecting those classes with a null class loader.
Parameters:
- initiatingLoader
- the initiating class loader.
- classCountPtr
- on return, points to the number of classes.
- classesPtr
- on return, points to an array of references, one for each class. Classes in the array are JNI global references and must be explicitly freed with the JNI function DeleteGlobalRef. The returned class array should be freed with Deallocate.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
Redefine Classes
typedef struct { jclass clazz; /* Class to be redefined */ jint class_byte_count; /* number of bytes defining class (below) */ jbyte *class_bytes; /* bytes defining class */ /* (in Class File Format of JVM spec) */ } JVMDI_class_definition; jvmdiError RedefineClasses(jint classCount, JVMDI_class_definition *classDefs)All classes given are redefined according to the definitions supplied. If any redefined methods have active stack frames, those active frames continue to run the bytecodes of the original method. The redefined methods will be used on new invokes. Any JVMDI function or event which returns a jmethodID, will return OBSOLETE_METHOD_ID when referring to the original method (for example, when examining a stack frame where the original method is still executing) unless it is equivalent to the redefined method (see below). The original method ID refers to the redefined method. Care should be taken thoughout a JVMDI client to handle OBSOLETE_METHOD_ID. If reseting of stack frames is desired, use PopFrame to pop frames with OBSOLETE_METHOD_IDs.
An original and a redefined method should be considered equivalent if:
- their bytecodes are the same except for indicies into the constant pool and
- the referenced constants are equal.
This function does not cause any initialization except that which would occur under the customary JVM semantics. In other words, redefining a class does not cause its initializers to be run. The values of preexisting static variables will remain as they were prior to the call. However, completely uninitialized (new) static variables will be assigned their default value.
If a redefined class has instances then all those instances will have the fields defined by the redefined class at the completion of the call. Preexisting fields will retain their previous values. Any new fields will have their default values; no instance initializers or constructors are run.
Threads need not be suspended.
All breakpoints in the class are cleared.
All attributes are updated.
No JVMDI events are generated by this function.
This is an optional feature which may not be implemented for all virtual machines. Examine can_redefine_classes, can_add_method and can_unrestrictedly_redefine_classes of GetCapabilities to determine whether this feature is supported in a particular virtual machine.
Parameters:
This function returns either a universal error or one of the following errors:
- classCount
- the number of classes specified in classDefs
- classDefs
- the array of new class definitions
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer: classDefs or one of class_bytes is NULL.
- JVMDI_ERROR_INVALID_CLASS
- An element of classDefs is not a valid class.
- JVMDI_ERROR_UNSUPPORTED_VERSION
- A new class file has a version number not supported by this VM.
- JVMDI_ERROR_INVALID_CLASS_FORMAT
- A new class file is malformed (The VM would return a ClassFormatError).
- JVMDI_ERROR_CIRCULAR_CLASS_DEFINITION
- The new class file definitions would lead to a circular definition (the VM would return a ClassCircularityError).
- JVMDI_ERROR_FAILS_VERIFICATION
- The class bytes fail verification.
- JVMDI_ERROR_NAMES_DONT_MATCH
- The class name defined in the new class file is different from the name in the old class object.
- JVMDI_ERROR_NOT_IMPLEMENTED
- No aspect of this functionality is implemented (can_redefine_classes capability is false).
- JVMDI_ERROR_ADD_METHOD_NOT_IMPLEMENTED
- A new class file would require adding a method, (and can_add_method capability is false).
- JVMDI_ERROR_SCHEMA_CHANGE_NOT_IMPLEMENTED
- The new class version changes fields (and can_unrestrictedly_redefine_classes is false).
- JVMDI_ERROR_HIERARCHY_CHANGE_NOT_IMPLEMENTED
- A direct superclass is different for the new class version, or the set of directly implemented interfaces is different (and can_unrestrictedly_redefine_classes is false).
- JVMDI_ERROR_DELETE_METHOD_NOT_IMPLEMENTED
- The new class version does not declare a method declared in the old class version. (and can_unrestrictedly_redefine_classes is false).
- JVMDI_ERROR_CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED
- The new version of a class has different class modifiers (public, abstract, final, ...) then the old version (and can_unrestrictedly_redefine_classes is false).
- JVMDI_ERROR_METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED
- The new version of a class has a different method modifier (public, abstract, synchronized, ...) then the old version (and can_unrestrictedly_redefine_classes is false).
Get Version Number
Return the JVMDI version via versionPtr The return value is the version identifier. The low-order 16 bits represent the minor version number. The next 12 bits represent the major version number. The high-order 4 bits are undefined.jvmdiError GetVersionNumber(jint *versionPtr)Parameters:
- versionPtr
- on return, points to the JVMDI version.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
Get Capabilities
Return via capabilitiesPtr the optional JVMDI features supported by this implementation. The capabilities structure contains a number of boolean flags indicating whether the named feature is supported.typedef struct { unsigned int can_watch_field_modification : 1; unsigned int can_watch_field_access : 1; unsigned int can_get_bytecodes : 1; unsigned int can_get_synthetic_attribute : 1; unsigned int can_get_owned_monitor_info : 1; unsigned int can_get_current_contended_monitor : 1; unsigned int can_get_monitor_info : 1; unsigned int reserved1 : 1; unsigned int reserved2 : 1; unsigned int reserved3 : 1; unsigned int can_pop_frame : 1; unsigned int reserved4 : 1; unsigned int can_redefine_classes : 1; unsigned int can_add_method : 1; unsigned int can_unrestrictedly_redefine_classes : 1; unsigned int reserved5 : 1; } JVMDI_capabilities; jvmdiError GetCapabilities(JVMDI_capabilities *capabilitiesPtr)Parameters:
- capabilitiesPtr
- on return, points to the JVMDI capabilities.
This function returns either a universal error or one of the following errors:
- JVMDI_ERROR_NULL_POINTER
- Invalid pointer.
Errors
Every JVMDI function returns a jvmdiError error code.
Universal Errors
The following errors may be returned by any JVMDI function (and are thus not listed in the function descriptions):
- JVMDI_ERROR_NONE
- No error has occurred. This is the error code that is returned on successful completion of the function.
- JVMDI_ERROR_OUT_OF_MEMORY
- The function needed to allocate memory and no more memory was available for allocation.
- JVMDI_ERROR_ACCESS_DENIED
- Debugging has not been enabled in this virtual machine. JVMDI cannot be used.
- JVMDI_ERROR_UNATTACHED_THREAD
- The thread being used to call this function is not attached to the virtual machine. Calls must be made from attached threads. See AttachCurrentThread() in the JNI invocation API.
- JVMDI_ERROR_VM_DEAD
- The virtual machine is not running.
- JVMDI_ERROR_INTERNAL
- An unexpected internal error has occurred.
Function Specific Errors
The following errors are returned by some JVMDI functions (and are listed in the function descriptions):
- JVMDI_ERROR_INVALID_THREAD
- passed thread is not a valid thread or has exited
- JVMDI_ERROR_INVALID_FIELDID
- invalid field
- JVMDI_ERROR_INVALID_METHODID
- invalid method
- JVMDI_ERROR_INVALID_LOCATION
- invalid location
- JVMDI_ERROR_INVALID_FRAMEID
- invalid jframeID
- There are no more Java programming language or JNI frames on the call stack.
- JVMDI_ERROR_OPAQUE_FRAME
- information about the frame is not available (e.g. for native frames)
- JVMDI_ERROR_NOT_CURRENT_FRAME
- operation can only be performed on current frame
- JVMDI_ERROR_TYPE_MISMATCH
- the variable is not an appropriate type for the function used
- JVMDI_ERROR_INVALID_SLOT
- invalid slot
- JVMDI_ERROR_DUPLICATE
- item already set
- JVMDI_ERROR_THREAD_NOT_SUSPENDED
- thread was not suspended
- JVMDI_ERROR_THREAD_SUSPENDED
- thread already suspended
- JVMDI_ERROR_INVALID_OBJECT
- invalid object
- JVMDI_ERROR_INVALID_CLASS
- invalid class
- JVMDI_ERROR_CLASS_NOT_PREPARED
- class has been loaded but not yet prepared
- JVMDI_ERROR_NULL_POINTER
- invalid pointer
- JVMDI_ERROR_ABSENT_INFORMATION
- The requested information is not available.
- JVMDI_ERROR_INVALID_EVENT_TYPE
- The specified event type id is not recognized.
- JVMDI_ERROR_NOT_IMPLEMENTED
- The functionality is not implemented in this virtual machine
- JVMDI_ERROR_INVALID_THREAD_GROUP
- thread group invalid
- JVMDI_ERROR_INVALID_PRIORITY
- invalid priority
- JVMDI_ERROR_NOT_FOUND
- Desired element (e.g. field or breakpoint) not found
- JVMDI_ERROR_INVALID_MONITOR
- invalid monitor
- JVMDI_ERROR_ILLEGAL_ARGUMENT
- illegal argument
- JVMDI_ERROR_NOT_MONITOR_OWNER
- This thread doesn't own the monitor.
- JVMDI_ERROR_ABSENT_INFORMATION
- Desired information is not available.
- JVMDI_ERROR_INTERRUPT
- The call has been interrupted before completion.
- JVMDI_ERROR_INVALID_TYPESTATE
- The state of the thread has been modified, and is now inconsistent.
- JVMDI_ERROR_UNSUPPORTED_VERSION
- A new class file has a version number not supported by this VM.
- JVMDI_ERROR_INVALID_CLASS_FORMAT
- A new class file is malformed (The VM would return a ClassFormatError).
- JVMDI_ERROR_CIRCULAR_CLASS_DEFINITION
- The new class file definitions would lead to a circular definition (the VM would return a ClassCircularityError).
- JVMDI_ERROR_ADD_METHOD_NOT_IMPLEMENTED
- A new class file would require adding a method, and can_add_method is false.
- JVMDI_ERROR_SCHEMA_CHANGE_NOT_IMPLEMENTED
- A new class file would require a schema change, and can_unrestrictedly_redefine_classes is false.
- JVMDI_ERROR_FAILS_VERIFICATION
- The class bytes fail verification.
- JVMDI_ERROR_HIERARCHY_CHANGE_NOT_IMPLEMENTED
- A direct superclass is different for the new class version, or the set of directly implemented interfaces is different and can_unrestrictedly_redefine_classes is false.
- JVMDI_ERROR_DELETE_METHOD_NOT_IMPLEMENTED
- The new class version does not declare a method declared in the old class version and can_unrestrictedly_redefine_classes is false.
- JVMDI_ERROR_NAMES_DONT_MATCH
- The class name defined in the new class file is different from the name in the old class object.
- JVMDI_ERROR_CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED
- The new version of a class has different class modifiers (public, abstract, final, ...) then the old version (and can_unrestrictedly_redefine_classes is false).
- JVMDI_ERROR_METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED
- The new version of a class has a different method modifier (public, abstract, synchronized, ...) then the old version (and can_unrestrictedly_redefine_classes is false).
Handling Events
- Introduction
- Single Step Event
- JVMDI_EVENT_SINGLE_STEP
- Breakpoint Event
- JVMDI_EVENT_BREAKPOINT
- Field Events
- JVMDI_EVENT_FIELD_ACCESS
- JVMDI_EVENT_FIELD_MODIFICATION
- Frame Events
- JVMDI_EVENT_FRAME_POP
- JVMDI_EVENT_METHOD_ENTRY
- JVMDI_EVENT_METHOD_EXIT
- Exception Event
- JVMDI_EVENT_EXCEPTION
- Exception Catch Event
- JVMDI_EVENT_EXCEPTION_CATCH
- User Defined Event
- JVMDI_EVENT_USER_DEFINED
- Thread Events
- JVMDI_EVENT_THREAD_END
- JVMDI_EVENT_THREAD_START
- Class Events
- JVMDI_EVENT_CLASS_LOAD
- JVMDI_EVENT_CLASS_UNLOAD
- JVMDI_EVENT_CLASS_PREPARE
- VM Initialization Event
- JVMDI_EVENT_VM_INIT
- VM Death Event
- JVMDI_EVENT_VM_DEATH
JVMDI clients can be informed of many events that occur in application programs.
To handle Events, designate a hook function with SetEventHook. For each event the hook function will be called with a JVMDI_Event argument describing the event type and, depending on the event, additional information. The hook function is usually called from within application threads and the JVMDI implementation does not queue events in any way. This means that event hook functions must be written carefully. Here are some general guidelines. See the individual event descriptions for further suggestions.
- Any exception thrown during the execution of an event hook can overwrite any current pending exception in the current application thread. Care must be taken to preserve a pending exception when an event hook makes a JNI call that might generate an exception.
- Event hook functions must be re-entrant. The JVMDI implementation does not queue events. If a JVMDI client needs to process events one at a time, it can use a raw monitor inside the event hook function to serialize event processing.
Some JVMDI events identify objects with JNI references. All such references are passed to the event hook function via the JVMDI_Event argument. All references in JVMDI events are JNI local references and will become invalid after the event hook returns. The JVMDI_Event data structure is allocated locally and deallocated when the event hook function returns.
Events can be enabled and disabled with the function SetEventNotificationMode. Some events are enabled at application startup; others are not. Refer to the documentation for this function for details.
A thread that generates an event does not change its execution status. If an event should cause a thread to be suspended, then the event hook function is responsible for explicitly suspending the thread with SuspendThread.
The JVMDI_Event contains the event kind and a union of event-specific structures containing more information.
typedef struct { jint kind; /* the discriminant */ union { /* kind = JVMDI_EVENT_SINGLE_STEP */ JVMDI_single_step_event_data single_step; /* kind = JVMDI_EVENT_BREAKPOINT */ JVMDI_breakpoint_event_data breakpoint; /* kind = JVMDI_EVENT_FRAME_POP */ /* kind = JVMDI_EVENT_METHOD_ENTRY */ /* kind = JVMDI_EVENT_METHOD_EXIT */ JVMDI_frame_event_data frame; /* kind = JVMDI_EVENT_FIELD_ACCESS */ JVMDI_field_access_event_data field_access; /* kind = JVMDI_EVENT_FIELD_MODIFICATION */ JVMDI_field_modification_event_data field_modification; /* kind = JVMDI_EVENT_EXCEPTION */ JVMDI_exception_event_data exception; /* kind = JVMDI_EVENT_EXCEPTION_CATCH */ JVMDI_exception_catch_event_data exception_catch; /* kind = JVMDI_EVENT_USER_DEFINED */ JVMDI_user_event_data user; /* kind = JVMDI_EVENT_THREAD_END or */ /* JVMDI_EVENT_THREAD_START */ JVMDI_thread_change_event_data thread_change; /* kind = JVMDI_EVENT_CLASS_LOAD, */ /* JVMDI_EVENT_CLASS_UNLOAD, or */ /* JVMDI_EVENT_CLASS_PREPARE */ JVMDI_class_event_data class_event; /* kind = JVMDI_EVENT_VM_DEATH, JVMDI_EVENT_VM_INIT */ /* no additional fields */ } u; } JVMDI_Event;More information on specific events is given in the sections below.
Single Step Events (JVMDI_EVENT_SINGLE_STEP)
typedef struct { jthread thread; jclass clazz; jmethodID method; jlocation location; } JVMDI_single_step_event_data;Single step events allow the JVMDI client to trace thread execution at the finest granularity allowed by the VM. A single step event is generated whenever a thread reaches a new location. Typically, single step events represent the completion of one VM instruction as defined the VM Specification; however, some implementations may define location differently. In any case the clazz, method, and location fields of the event structure uniquely identify the current location and allow the mapping to source file and line number when that information is available.
No single step events are generated from within native methods.
Single step events are disabled by default and can be enabled for a thread by calling SetEventNotificationMode
Breakpoint Events (JVMDI_EVENT_BREAKPOINT)
typedef struct { jthread thread; jclass clazz; jmethodID method; jlocation location; } JVMDI_breakpoint_event_data;Breakpoint Events are generated whenever a thread reaches a location designated as a breakpoint with SetBreakpoint. The clazz, method, and location fields of the event structure uniquely identify the current location and allow the mapping to source file and line number when that information is available.
Breakpoint reporting, in general, can be enabled or disabled by calling SetEventNotificationMode and are enabled by default. If they are disabled, set breakpoints are ignored.
Field Events (JVMDI_EVENT_FIELD_ACCESS, JVMDI_EVENT_FIELD_MODIFICATION)
/* kind = JVMDI_EVENT_FIELD_ACCESS */ typedef struct { jthread thread; jclass clazz; jmethodID method; jlocation location; jclass field_clazz; jobject object; jfieldID field; } JVMDI_field_access_event_data; /* kind = JVMDI_EVENT_FIELD_MODIFICATION */ typedef struct { jthread thread; jclass clazz; jmethodID method; jlocation location; jclass field_clazz; jobject object; jfieldID field; char signature_type; jvalue new_value; } JVMDI_field_modification_event_data;Field Events are generated whenever a thread accesses or modifies a field designated as a watchpoint with SetFieldAccessWatch or with SetFieldModificationWatch. The clazz, method, and location fields of the event structures uniquely identify the current location and allow the mapping to source file and line number when that information is available. The field_clazz and field fields uniquely identify the field which is being accessed or modified. The object identifies the containing object if the field is an instance field. It is NULL otherwise.
Field watchpoint reporting, in general, can be enabled or disabled by calling SetEventNotificationMode and are enabled by default. If they are disabled, set watches are ignored.
Frame Events (JVMDI_EVENT_FRAME_POP, JVMDI_EVENT_METHOD_ENTRY, JVMDI_EVENT_METHOD_EXIT)
typedef struct { jthread thread; jclass clazz; jmethodID method; jframeID frame; } JVMDI_frame_event_data;Method entry events are generated upon entry of Java programming language or native methods. Method exit events are generated upon exit from a Java programming language or native methods. Frame pop events are generated upon exit from a single method in a single frame as specified in a call to NotifyFramePop. If a method terminates by throwing an exception to its caller, neither a method exit event nor a frame pop event will be generated. JVMDI clients can check for this occurrence by monitoring exception catch events
The clazz and method fields uniquely identify the method being entered or exited. The frame field provides access to the stack frame for the method. On method entry, the location reported by GetFrameLocation identifies the initial executable location in the method. On method exit or frame pop, the location reported by GetFrameLocation identifies the executable location in the returning method, immediately prior to the return.
Method entry and exit are disabled by default and can be enabled by calling SetEventNotificationMode. Frame pop events are enabled by default and can be disabled similarly.
Exception Events (JVMDI_EVENT_EXCEPTION)
typedef struct { jthread thread; jclass clazz; jmethodID method; jlocation location; jobject exception; jclass catch_clazz; jmethodID catch_method; jlocation catch_location; } JVMDI_exception_event_data;Exception events are generated whenever an exception is first detected in a Java programming language method. The exception may have been thrown by a Java programming language or native method, but in the case of native methods, the event is not generated until the exception is first seen by a Java programming language method. If an exception is set and cleared in a native method (and thus is never visible to Java programming language code), no exception event is generated.
The clazz, method, and location fields of the event structure uniquely identify the current location (where the exception was detected) and allow the mapping to source file and line number when that information is available. The exception field identifies the thrown exception object. The catch_clazz, catch_method, and catch_location identify the location of the catch clause, if any, that handles thrown exception. If there is no such catch clause, each field is set to 0. There is no guarantee that the thread will ever reach this catch clause. If there are native methods on the call stack between the throw location and the catch clause, the exception may be reset by one of those native methods. JVMDI clients can check for this occurrence by monitoring exception catch events
Exception events are enabled by default and can be disabled by calling SetEventNotificationMode.
Exception Catch Events (JVMDI_EVENT_EXCEPTION_CATCH)
typedef struct { jthread thread; jclass clazz; jmethodID method; jlocation location; jobject exception; } JVMDI_exception_catch_event_data;Exception catch events are generated whenever a thrown exception is caught. If the exception is caught in a Java programming language method, the event is generated when the catch clause is reached. If the exception is caught in a native method, the event is generated as soon as control is returned to a Java programming language method. Exception catch events are generated for any exception for which a throw was detected in a Java programming language method.
The clazz, method, and location fields of the event structure uniquely identify the current location and allow the mapping to source file and line number when that information is available. For exceptions caught in a Java programming language method, the exception object identifies the exception object. Exceptions caught in native methods are not necessarily available by the time the exception catch is reported, so the exception field is set to NULL.
Exception catch events are disabled by default and can be enabled by calling SetEventNotificationMode.
User Defined Events (JVMDI_EVENT_USER_DEFINED)
typedef struct { jobject object; jint key; } JVMDI_user_event_data;The meaning of user defined events and the fields in the user event data structure are defined by particular JVMDI implementations.
Thread Events (JVMDI_EVENT_THREAD_END, JVMDI_EVENT_THREAD_START)
typedef struct { jthread thread; } JVMDI_thread_change_event_data;Thread start events are generated by a new thread before its initial method executes. Thread end events are generated by a terminating thread after its initial method has finished execution. A thread may be listed in the array returned by GetAllThreads before its thread start event is generated and after its thread end event is generated. It is possible for other events to be generated for a thread before its thread start event, but no events are generated after its thread end event.
Thread events are enabled by default and can be disabled by calling SetEventNotificationMode.
Class Events (JVMDI_EVENT_CLASS_LOAD, JVMDI_EVENT_CLASS_UNLOAD, JVMDI_EVENT_CLASS_PREPARE)
typedef struct { jthread thread; jclass clazz; } JVMDI_class_event_data;Class events signal a change in status for a particular class.
A class load event is generated when a class is first loaded. The order of class load events are generated by a particular thread are guaranteed to match the order of class loading within that thread. Arrays of non-primitive types have class load events. Arrays of primitive types do not have class load events (they are considered loaded at the time of VM initialization). Primitive classes (for example, java.lang.Integer.TYPE) do not have class load events.
A class prepare event is generated when class preparation is complete. At this point, class fields, methods, and implemented interfaces are available, and no code from the class has been executed. Since array classes never have fields or methods, class prepare events are not generated for them. Class prepare events are not generated for primitive classes (for example, java.lang.Integer.TYPE).
A class unload event is generated when the class is about to be unloaded. Class unload events take place during garbage collection and must be handled extremely carefully. The garbage collector holds many locks and has suspended all other threads, so the event handler cannot depend on the ability to acquire any locks. The class unload event handler should do as little as possible, perhaps by queueing information to be processed later.
Class events are enabled by default and can be disabled by calling SetEventNotificationMode.
VM Initialization Event (JVMDI_EVENT_VM_INIT)
The VM initialization event signals the completion of VM initialization. Once this event is generated, the JVMDI client is free to call any JNI or JVMDI function. The VM initialization event can be preceded by or can be concurrent with other events, but the preceding events should be handled carefully, if at all because the VM has not completed its initialization. The thread start event for the main application thread is guaranteed not to occur until after the handler for the VM initialization event returns.
VM Death Event (JVMDI_EVENT_VM_DEATH)
The VM death event notifies the JVMDI client of the termination of the VM.Multiple Co-located Events
In many situations it is possible for multiple events to occur at the same location in one thread. When this happens, all of the events are reported through the event hook in the order specified in the following paragraphs.If the current location is at the entry point of a method, the JVMDI_EVENT_METHOD_ENTRY event is reported before any other event at the current location in the same thread.
If an exception catch has been detected at the current location, (either because it is the beginning of a catch clause or a native method which cleared a pending exception has returned), the JVMDI_EVENT_EXCEPTION_CATCH event is reported before any other event at the current location in the same thread.
If a JVMDI_EVENT_SINGLE_STEP event or JVMDI_EVENT_BREAKPOINT event is triggered at the current location, the event is defined to occur immediately before the code at the current location is executed. These events are reported before any events which are triggered by the execution of code at the current location in the same thread (specifically, JVMDI_EVENT_EXCEPTION, JVMDI_EVENT_FIELD_ACCESS, and JVMDI_EVENT_FIELD_MODIFICATION). If both a step and breakpoint event are triggered for the same thread and location, the step event is reported before the breakpoint event.
If the current location is the exit point of a method (that is, the last location before returning to the caller), the JVMDI_EVENT_METHOD_EXIT event and the JVMDI_EVENT_FRAME_POP event (if requested) are reported after all other events at the current location in the same thread. There is no specified ordering of these two events with respect to each other.
Co-located events can be triggered during the processing of some other event by the JVMDI client at the same location in the same thread. If such an event, of type y, is triggered during the processing of an event of type x, and if x precedes y in the ordering specified above, then the co-located event y is reported for the current thread and location. If x does not precede y, then y is not reported for the current thread and location. For example, if a breakpoint is set at the current location during the processing of JVMDI_EVENT_SINGLE_STEP, that breakpoint will be reported before the thread moves off the current location.
The following events are never considered to be co-located with other events.
- JVMDI_EVENT_USER_DEFINED
- JVMDI_EVENT_VM_INIT
- JVMDI_EVENT_VM_DEATH
- JVMDI_EVENT_THREAD_START
- JVMDI_EVENT_THREAD_END
- JVMDI_EVENT_CLASS_LOAD
- JVMDI_EVENT_CLASS_UNLOAD
- JVMDI_EVENT_CLASS_PREPARE
Starting a VM with a JVMDI Client
The initial loading of a JVMDI client at VM startup can vary from VM to VM. The following description applies to the Sun J2SE SDK 1.2 classic VM for Windows and Solaris.
The following command-line arguments are required on VM startup to properly load and run JVMDI clients.
- -Xdebug
- Enables debugging
- -Xnoagent
- Prevents the default debug agent (used with jdb) from running.
- -Djava.compiler=NONE
- Disables the JIT. The classic VM does not support debugging with the JIT enabled.
- -Xrun
: - Identifies the library containing the JVMDI client as well as an options string to be passed in at startup. The library must export a startup function with the following prototype.
JNIEXPORT jint JNICALL JVM_OnLoad(JavaVM *vm, char *options, void *reserved)This function will be called at startup by the VM. For example, if the option -Xrunfoo:opt1,opt2 is specified, the VM will attempt to load the shared library foo.dll under Windows or libfoo.so under Solaris. It will then attempt to find JVM_OnLoad and call it with "opt1,opt2" as the second argument. Since the VM is not initialized at the time of this call, there is very little that can be done safely inside JVM_OnLoad. It can safely process the options and set an event hook with SetEventHook. Once that event hook is called for the VM initialization event, the JVMDI client can complete its initialization.