| # JavaTM Virtual Machine Debug Interface Reference

## Contents

> Introduction
> Using JVMDI Functions
> Errors
> Handling Events
> Starting a VM with a JVMDI Client

## Introduction

Note: JVMDI is deprecated as of J2SE 5.0. JVMTI should be used instead.

The JavaTM 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 JavaTM 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 was the lowest layer within the Java Platform Debugger Architecture, this role is now handled by JVMTI. 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
  - Set Allocation Hooks
  - Allocate Memory
  - Deallocate Memory
- Thread Execution Functions
  - Get Thread Status
  - Get All Threads
  - Suspend Thread
  - Suspend Thread List
  - Resume Thread
  - Resume Thread List
  - Stop Thread
  - Interrupt Thread
  - Get Thread Info
  - Get Owned Monitor Info
  - Get Current Contended Monitor
  - Run Debug Thread
- Thread Groups
  - Get Top Thread Groups
  - Get Thread Group Info
  - Get Thread Group Children
- Stack Frame Access
  - Get Thread's Frame Count
  - Get Thread's Current Frame
  - Pop Frame from Thread's Stack
  - Get Caller Frame
  - Frame Location
  - Notify Frame Pop
- Local Variable Access
  - Get Local Variable
  - Set Local Variable
- Breakpoints
  - Set a Breakpoint
  - Clear a Breakpoint
  - Clear All Breakpoints
- Watched Fields
  - Set a Field Access Watch
  - Clear a Field Access Watch
  - Set a Field Modification Watch
  - Clear a Field Modification Watch
- Class Information
  - Class Signature
  - Class Status
  - Source File Name
  - Class Modifier Flags
  - Class Methods
  - Class Fields
  - Implemented Interfaces
  - Is an Interface
  - Is an Array
  - Class Loader
  - Source Debug Extension
- Object Information
  - Object Hash Code
  - Get Monitor Info
- Field Information
  - Field Name and Signature
  - Field Declaring Class
  - Field Modifier Flags
  - Is Field Synthetic
- Method Information
  - Method Name and Signature
  - Method Declaring Class
  - Method Modifier Flags
  - Maximum Stack
  - Local Slots
  - Argument Slots
  - Source Line Numbers
  - Method Location
  - Local Variables
  - Exception Handlers
  - Thrown Exceptions
  - Get Bytecodes
  - Is Method Native
  - Is Method Synthetic
- Raw Monitor Support
  - Create Raw Monitor
  - Destroy Raw Monitor
  - Raw Monitor Enter
  - Raw Monitor Exit
  - Raw Monitor Wait
  - Raw Monitor Notify
  - Raw Monitor Notify All
- Events
  - Set Event Hook
  - Enable/Disable Events
- Miscellaneous Functions
  - Get Loaded Classes
  - Get Classloader Classes
  - Redefine Classes
  - Get Version Number
  - Get Capabilities

## 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:

> 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` or `SuspendThreadList` 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.

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 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:

> 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`.

This function returns either a universal error or one of the following errors:

> `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` or `ResumeThreadList`.

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.

### Suspend Thread List

>     jvmdiError
>     SuspendThreadList(jint reqCount, jthread *reqList, jvmdiError *results)

Suspend the reqCount threads specified in the reqList array. If the calling thread is specified in the reqList array, this function will not return until some other thread calls `ResumeThread` or `ResumeThreadList`.

Parameters:

> reqCount
>   the number of threads to suspend
> reqList
>   the list of threads to suspend
> results
>   the list of per-thread suspend results

This function returns either a universal error or one of the following errors:

> `JVMDI_ERROR_ILLEGAL_ARGUMENT`
>   reqCount is less than zero (0).

Note that the function return value does not include per-thread error conditions; per-thread error conditions are returned via the results array.

The results array element for a specific thread contains either a universal error or one of the following errors:

> `JVMDI_ERROR_INVALID_THREAD`
>   `thread` was invalid.

> `JVMDI_ERROR_THREAD_SUSPENDED`
>   Thread already suspended.

> `JVMDI_ERROR_NULL_POINTER`
>   Invalid pointer.

### Resume Thread

>     jvmdiError
>     ResumeThread(jthread thread)

Resume a suspended thread. Any thread suspended through `java.lang.Thread.suspend()`, `SuspendThread` or `SuspendThreadList` 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.

### Resume Thread List

>     jvmdiError
>     ResumeThreadList(jint reqCount, jthread *reqList, jvmdiError *results)

Resume the reqCount threads specified in the reqList array. Any thread suspended through `java.lang.Thread.suspend()`, `SuspendThread`, or `SuspendThreadList` will resume execution.

Parameters:

> reqCount
>   the number of threads to resume
> reqList
>   the list of threads to resume
> results
>   the list of per-thread resume results

This function returns either a universal error or one of the following errors:

> `JVMDI_ERROR_ILLEGAL_ARGUMENT`
>   reqCount is less than zero (0).

The results array element for a specific thread contains 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.

> `JVMDI_ERROR_NULL_POINTER`
>   Invalid pointer.

### 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

>     jvmdiError
>     GetThreadGroupChildren(jthreadGroup group,
>                      jint *threadCountPtr, jthread **threadsPtr,
>                      jint *groupCountPtr, jthreadGroup **groupsPtr)

Get the live threads and active thread groups created within the given thread group. A thread is alive if it has been started and has not yet been stopped. See java.lang.ThreadGroup for information about 'active' ThreadGroups.

Parameters:

> group
>   the group to query.
> threadCountPtr
>   on return, points to the number of alive owned threads
> threadsPtr
>   on return, refers to a pointer to the alive owned threads 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 active child thread groups
> groupsPtr
>   on return, refers to a pointer to the active 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:

> thread
>   The thread to query
> countPtr
>   on return, points to the number of frames in the call stack.

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 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:

> thread
>   The thread to query
> framePtr
>   on return, points to the frame ID for the current stack frame of this thread.

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 was not suspended.

> `JVMDI_ERROR_NO_MORE_FRAMES`
>   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 frame for the caller of the topmost stack 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 frames may not be popped, nor may a Java frame be popped if its caller is native code.

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:

> thread
>   The thread whose top frame is to be popped.

This function returns either a universal error or one of the following errors:

> `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.

> `JVMDI_ERROR_NO_MORE_FRAMES`
>   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

>     jvmdiError
>     GetCallerFrame(jframeID called, jframeID *framePtr)

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.

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`.

> `JVMDI_ERROR_NO_MORE_FRAMES`
>   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_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_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

>     jvmdiError
>     ClearAllBreakpoints()

Clear all breakpoints in this virtual machine.

## 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

>     jvmdiError
>     GetClassSignature(jclass clazz, char **sigPtr)

For the class indicated by `clazz`, return the class signature via `sigPtr`. The return value is a UTF-8 string.

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

>     jvmdiError
>     GetSourceFileName(jclass clazz, char **sourceNamePtr)

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.

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

>     jvmdiError
>     GetClassModifiers(jclass clazz, jint *modifiersPtr)

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.

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

>     jvmdiError
>     GetClassMethods(jclass clazz, jint *methodCountPtr, jmethodID **methodsPtr)

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).

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

>     jvmdiError
>     GetClassFields(jclass clazz, jint *fieldCountPtr, jfieldID **fieldsPtr)

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.

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

>     jvmdiError
>     GetImplementedInterfaces(jclass clazz,
>                            jint *interfaceCountPtr,
>                            jclass **interfacesPtr);

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).

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

>     jvmdiError
>     IsInterface(jclass clazz, jboolean *isInterfacePtr)

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.

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

>     jvmdiError
>     IsArrayClass(jclass clazz, jboolean *isArrayClassPtr)

Determines whether a class object reference represents an array. The `jboolean` result is `JNI_TRUE` if the class is an array, `JNI_FALSE` otherwise.

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

>     jvmdiError
>     GetClassLoader(jclass clazz, jobject *classloaderPtr)

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`.

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

>     jvmdiError
>     GetSourceDebugExtension(jclass clazz, char **sourceDebugExtensionPtr)

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`.

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

  >     jvmdiError
  >     GetObjectHashCode(jobject object, jint *hashCodePtr)

  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 life

  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

  >     jvmdiError
  >     GetFieldName(jclass clazz, jfieldID field,
  >                        char **namePtr, char **signaturePtr)

  For the field indicated by `clazz` and `field`, return the field name via `namePtr` and field signature via `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

  >     jvmdiError
  >     GetFieldDeclaringClass(jclass clazz, jfieldID field, jclass *declaringClassPtr)

  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.

  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

  >     jvmdiError
  >     GetFieldModifiers(jclass clazz, jfieldID field, jint *modifiersPtr)

  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.

  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

  >     jvmdiError
  >     GetMethodDeclaringClass(jclass clazz, jmethodID method,
  >                                      jclass *declaringClassPtr)

  For the method indicated by `clazz` and `method`, return the Class that defined it via `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

  >     jvmdiError
  >     GetMethodModifiers(jclass clazz, jmethodID method,
  >                              jint *modifiersPtr)

  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.

  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

  >     jvmdiError
  >     GetMaxStack(jclass clazz, jmethodID method, jint *maxPtr)

  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.

  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

  >     jvmdiError
  >     GetMaxLocals(jclass clazz, jmethodID method,
  >                       jint *maxPtr);

  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.

  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

  >     jvmdiError
  >     GetArgumentsSize(jclass clazz, jmethodID method, jint *sizePtr)

  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.

  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

  >     jvmdiError
  >     GetLineNumberTable(jclass clazz, jmethodID method,
  >      			 jint *entryCountPtr,
  >                  JVMDI_line_number_entry **tablePtr)

  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:

  >     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

  >     jvmdiError
  >     GetMethodLocation(jclass clazz, jmethodID method,
  >                             jlocation *startLocationPtr,
  >                             jlocation *endLocationPtr)

  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.

  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

  >     jvmdiError
  >     GetLocalVariableTable(jclass clazz, jmethodID method,
  >                                 jint *entryCountPtr,
  >                                 JVMDI_local_variable_entry **tablePtr)

  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:

  >     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

  >     jvmdiError
  >     GetExceptionHandlerTable(jclass clazz, jmethodID method,
  >                                    jint *entryCountPtr,
  >                                    JVMDI_exception_handler_entry **tablePtr)

  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:

  >     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

  >     jvmdiError
  >     GetThrownExceptions(jclass clazz, jmethodID method,
  >                               jint *exceptionCountPtr, jclass **exceptionsPtr)

  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`.

  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

  >     jvmdiError
  >     GetBytecodes(jclass clazz, jmethodID method, jint *bytecodeCountPtr,
  >                              jbyte **bytecodesPtr)

  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`.

  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

  >     jvmdiError
  >     CreateRawMonitor(char *name, JVMDI_RawMonitor *monitorPtr)

  Create a raw monitor.

  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

  >     jvmdiError
  >     DestroyRawMonitor(JVMDI_RawMonitor monitor)

  Destroy the raw 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 Enter

  >     jvmdiError
  >     RawMonitorEnter(JVMDI_RawMonitor monitor)

  Gain exclusive ownership of a raw 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

  >     jvmdiError
  >     RawMonitorExit(JVMDI_RawMonitor monitor)

  Release exclusive ownership of a raw 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 Wait

  >     jvmdiError
  >     RawMonitorWait(JVMDI_RawMonitor monitor, jlong millis)

  Wait for notification of the raw monitor.

  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

  >     jvmdiError
  >     RawMonitorNotify(JVMDI_RawMonitor monitor)

  Notify a single thread waiting on the raw 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

  >     jvmdiError
  >     RawMonitorNotifyAll(JVMDI_RawMonitor monitor)

  Notify all threads waiting on the raw 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

  >     typedef void (*JVMDI_EventHook)(JNIEnv *env , JVMDI_Event *event);

  >     jvmdiError
  >     SetEventHook(JVMDI_EventHook hook)

  Set the function to be called on every event. Details on events are described later in this document.

  Parameters:

  > hook
  >   the new event hook, or NULL to remove the existing hook.

  This function returns a universal error on error.

  ### Enable/Disable Events

  >     jvmdiError
  >     SetEventNotificationMode(jint mode, jint eventType, jthread thread, ...)

  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.

  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.

  - JVMDI_EVENT_SINGLE_STEP
  - JVMDI_EVENT_EXCEPTION_CATCH
  - JVMDI_EVENT_METHOD_ENTRY
  - JVMDI_EVENT_METHOD_EXIT
  Set the function to be called on every event. Details on events are described later in this document.

  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_ID`s.

  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:

  > classCount
  >   the number of classes specified in `classDefs`
  > classDefs
  >   the array of new class definitions

  This function returns either a universal error or one of the following errors:

  > `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

  >     jvmdiError
  >     GetVersionNumber(jint *versionPtr)

  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.

  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

  >     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)

  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.

  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 NULL, 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`

  `JVMDI_ERROR_NO_MORE_FRAMES`
    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 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.

  Copyright © 1996-2004 Sun Microsystems, Inc. All Rights Reserved. Send questions or comments to: java-debugger@sun.com. |