Working with MS VM
 
 

Microsoft VM   Previous VM Next
Java Language Debug Interfaces   Previous VM Next

 

Using the Java Debug Interfaces

The following sections describe in detail how to use the Java debug interfaces. They include discussion of the following topics:

General Considerations when Using the Java Debug Interfaces
Enabling Debugging in the Microsoft VM
Registering with the Java Debug Manager
Enumerating Active Java Processes
Registering with a Remote Process
Implementing Callback Notification Interfaces
Retrieving Static Information
Enumerating Static Fields
Enumerating Line Number Information
Retrieving Dynamic Information
Enumerating Dynamic Fields
Controlling Execution
Enumerating Thread Groups, Threads, and Stack Frames
Controlling Execution with Remote Threads
Accessing Call Stacks

General Considerations when Using the Java Debug Interfaces

The Java debug interfaces consist of a large collection of COM objects with many methods. The design of many of these interfaces and methods, however, follow a consistent design pattern.

Communication between the debugger and the VM is handled through COM interfaces. The debugger requests information and communicates with the VM by calling methods on COM objects implemented by the VM. Similarly, the Microsoft VM runtime notifies the debugger program of events, and then and provides the requested information by calling methods on COM objects that the debugger implements. The debugger registers these callbacks by calling a register callback method.

The COM objects implemented by the Microsoft VM use consistent class factory and get methods to handle lists of similar objects. Many of the Getxx methods return an enumerator object. These different enumerator objects (for processes, threads, fields, and so on) implement a nearly identical set of methods. These methods support returning an array of objects, skipping some number of objects, resetting the enumerator to the beginning of the list, copying the current enumerator position to another object (cloning), and getting only the next object.

The Java debug interfaces use a consistent hierarchy of objects. The enumeration methods allow the debugger program to move down the hierarchy of objects. Various Getxx methods (GetContainer, GetSuperClass, and so on) allow the debugger program to move up the hierarchy.

Because the Java debug interfaces are based on COM, some general considerations apply when calling the interfaces that are implemented by the Microsoft VM.

Any memory that a debugger program allocates for use as a buffer that is passed as a parameter to any of these COM interfaces (an [in,out] or an [out] parameter as documented in the reference section on the Java debug interfaces) must be allocated using the CoTaskMemAlloc function. When this memory is no longer needed, it must be released using the CoTaskMemFree function. This is a COM requirement because the memory is being allocated across processes. It is also a necessity for DCOM compatibility.

If the debugger program continues to use any COM objects that are created as parameters to a method, the reference count for that object may need to be incremented to ensure that the object remains viable for the duration of the method call. This can be accomplished by calling the Addref method on the COM interface. The debugger program decrements the reference count on the object using the Release method when this object is no longer needed.

Enabling Debugging in the Microsoft VM

For the Java debug interfaces to be used, debugging must be enabled in the Microsoft VM before the Java application or applet begins execution. Debugging can be enabled in the Microsoft VM for Java in two ways:

  • Defining particular environment variables

  • Creating particular Win32 registry settings

The preferred method to enable debugging is to set special environment variables before starting the Microsoft VM (before launching Microsoft® Internet Explorer, for example) and executing the Java application or applet. Note that the value of these environment variables (when set) override the equivalent settings in the registry. The environment variables that may be used by a debugger are shown in the following table.

Environment Variable Description and Values
MSJAVA_ENABLE_DEBUGGING Enables debugging when set to some value greater than 0. Valid values must be less than the value of a GUID.
MSJAVA_DEBUGGING_FLAGS Specifies options for debugging, most of which deal with issues when debugging a mixture of native code and Java.
MSJAVA_ENABLE_FI Enables the fast interpreter when set to some value that is non-zero. If this environment variable is not set and the equivalent registry value is not set, the fast interpreter is enabled by default.
MSJAVA_ENABLE_JIT Enables the Just-In-Time (JIT) compiler when set to some value that is non-zero. If this environment variable is not set and the equivalent registry value is not set, JIT is enabled by default.

If the MSJAVA_ENABLE_DEBUGGING string exists in the Win32 environment space and is set to some value greater than 0 for a process, debugging is enabled in any Microsoft VM that subsequently begins executing within this environment.

If the MSJAVA_DEBUGGING_FLAGS string exists in the Win32 environment space, the value it is set to specifies a set of options that control special features of the Microsoft VM. These options can be a combination of the following.

Option Value Description
MSJDBG_AD2_DEBUGGING 0x04 When set, this enables additional semantics, enabling some new Java interfaces and changing the behavior of some older Java interfaces.
MSJDBG_NO_HARDWARE_BREAKPOINTS 0x08 When set, this notifies the Microsoft VM that hardware breakpoints should not be used on Microsoft® Windows NT® being run on Intel processors. If this value and the following value are not set, data breakpoints are available. When using a native debugger, such as Microsoft® Visual C++®, set this value. This option is ignored on DEC alpha systems running Windows NT. Hardware breakpoints are not used on Microsoft® Windows 95®.
MSJDBG_NO_PAGE_BREAKPOINTS 0x10 When set, this notifies the Microsoft VM that memory page faults for data breakpoints should not be used (applies to both Microsoft® Windows 95 and Windows NT being run on Intel processors). If this value and the previous value are not set, data breakpoints are available. When using Visual C++ for debugging, set this value. This option is ignored on DEC alpha systems running Windows NT.
MSJDBG_ENABLE_JIT_COMPILED_CODE_DEBUGGING 0x40 When set, this notifies the Microsoft VM that Just-In-Time (JIT) code debugging is disabled.

Debugging can also be enabled and debug options can be configured through the use of registry settings on Windows 95 and Windows NT. The registry settings that affect the Microsoft VM when used with these debug interfaces are located under the following keys:

HKEY_LOCAL_MACHINE\Software\Microsoft\Java VM

Note the presence of a space between Java and VM in this registry node.

Under this node, the following entries and values may be entered or modified.

Debug

When this key exists before the Microsoft VM begins execution, debugging will be enabled.

DebuggingFlags

Set the value of this entry to a DWORD that indicates the value of the debug options.

MSDebug

When this key exists before the Microsoft VM begins execution, active debugging (AD2) will be enabled.

By default, when the Microsoft VM is installed, these registry entries are not created.

HKEY_LOCAL_MACHINE\CurrentUser\Software\Microsoft\Java VM

Note the presence of a space between Java and VM in this registry node.

Under this node, the following entries and values may be entered or modified.

EnableFI

Set the value of this entry to a DWORD that indicates whether the fast interpreter is enabled. A non-zero value enables the fast interpreter, while a value of zero disables this feature. The default value for this option is enabled.

EnableJIT

Set the value of this entry to a DWORD that indicates whether the Just-In-Time (JIT) compiler is enabled. A non-zero value enables the JIT compiler, while a value of zero disables this feature. The default value for this option is enabled.

EnableJitCompiledCodeDebugging

Set the value of this entry to a DWORD that indicates whether Just-In-Time (JIT) code debugging is enabled. A non-zero value enables JIT code debugging, while a value of zero disables this feature. The default value for this option is enabled. By default, when the Microsoft VM is installed, these registry entries are not created. Registry settings can be set using code similar to the following:

const char s_cszDebugKey[] = "Software\\Microsoft\\Java VM\\Debug";

// Create the Microsoft VM Debug key; return TRUE on success.
static BOOL CreateDebugKey(void)
{
    BOOL bResult;
    DWORD dwDisposition;
    HKEY hkeyDebug;

    bResult = ( RegCreateKeyEx(HKEY_LOCAL_MACHINE, s_cszDebugKey, 0,
                NULL, 0, KEY_WRITE, NULL, &hkeyDebug, &dwDisposition) 
                == ERROR_SUCCESS);

    if (bResult) RegCloseKey(hkeyDebug);

    return(bResult);
}

Exercise caution when using these registry settings for enabling use of the Java debug interfaces because these settings will affect all Java applications and applets started under the Microsoft VM. Enabling debugging disables certain optimizations in the Microsoft VM and requires more resources to be used. This option may disable the JIT compiler and invoke a slower than usual version of the Java bytecode interpreter, which will slow down the execution of all Java applications and applets. If the Debug registry entry is not explicitly removed when debugging is no longer needed, the execution performance of all Java applications and applets will be adversely affected. Registry settings can be removed using code similar to the following.

// Delete the Microsoft VM Debug key; return TRUE is successful.
static BOOL DeleteDebugKey(void)
{
    return ( RegDeleteKey(HKEY_LOCAL_MACHINE, s_cszDebugKey) == 
           ERROR_SUCCESS);
}

Registry entries can also be removed or modified using the regedit.exe utility that is included with Windows 95 and Windows NT.

Registering with the Java Debug Manager

To use the Java debug interfaces, a debugger program must call specific methods of the registration interfaces implemented by the Microsoft VM. Its registration interfaces are implemented as follows.

Registration Interfaces Inherits From Description
IRemoteDebugManager IUnknown This object manages all the processes that can be debugged and connects a debugger program to them when requested. This COM object must be initialized first before any other registration interfaces are used. The debugger program must then call the RegisterCallback method on this object's interface to provide a callback through which the Microsoft VM communicates with the debugger.
IEnumRemoteProcess IUnknown This object allows a debugger to enumerate all Java processes currently running in the Microsoft VM.
IJavaEnumRemoteProcess IEnumRemoteProcess This object inherits from the IEnumRemoteProcess interface (adds one new method) and allows a debugger to enumerate all Java processes currently running in the Microsoft VM.
IRemoteProcess IUnknown The interface pointer to this object represents a single Java process running within the Microsoft VM. Note that this object does not represent the Win32 operating system process that the Microsoft VM is being run in.
IRemoteProcessEx IRemoteProcess The interface pointer to this object represents a single Java process running within the Microsoft VM. Note that this object does not represent the Win32 operating system process that the Microsoft VM is being run in. This interface inherits from IRemoteProcess and adds one new method.

To register with the Microsoft VM, an application must first call the COM library function CoCreateInstance or CoCreateInstanceEx, passing in the class identifier (CLSID) of the debug manager, CLDID_RemoteJavaDebugManager, and interface identifier (IID) of the IRemoteDebugManager interface. CoCreateInstanceEx takes an additional parameter that specifies the host for use with DCOM. The COM library then uses the CLSID to find the entry for this object’s class in the system registry and starts the appropriate COM server.

The CLSID for the IRemoteDebugManager is defined in the JDbgGUID.h file. The IID for the IRemoteDebugManager object and the other Java debug interfaces are defined in the JavaDbg.h file that is installed in the Include directory of the SDK for Java. The JavaDbg.h include file also contains function prototypes for the methods supported by these interfaces.

The following sample code illustrates how these functions might be used to start a local server.

#include <JavaDbg.h>
#include <JDbgGUID.h

    HRESULT hr;
    hr = CoInitialize(NULL);   // Initialize OLE on this thread.

    if (SUCCEEDED(hr)) {
        IRemoteDebugManager *pirdm;

        // Create a RemoteJavaDebugManager to initiate debugging.

        hr = CoCreateInstance(CLSID_RemoteJavaDebugManager, NULL,
                              CLSCTX_LOCAL_SERVER,
                              IID_IRemoteDebugManager,
                              (PVOID *)&pirdm);

        if (hr == S_OK) {
            // Continue working if okay.
        }
        // Uninitialize OLE on this thread when done.
        CoUninitialize();

The debugger program must then register with the Debug Manager in the Microsoft VM, passing its own callback interface pointer through which this virtual machine will communicate with the debugger. The callback functions provided by the debugger must be implemented as methods on COM objects that represent the Notification interfaces, which will be addressed later in this topic.

The IRemoteDebugManager interface implements the following methods that may be called by a debugger.

Method Description
RegisterCallback The debugger program calls this method to provide a callback for receiving notification when new Java processes are created. The debugger must pass an interface to its own COM object that implements IRemoteDebugManagerCallback. The Microsoft VM communicates with the debugger by calling various methods on this callback interface.
Detach The debugger program calls this method to detach its callback (IRemoteDebugManagerCallback) that was attached by some previous call to RegisterCallback. Call this method before the debugger exits.
GetActiveProcesses This method is used to return an interface to an enumerator object (IJavaEnumRemoteProcess) for all the Java processes currently running in the Microsoft VM.
RequestCreateEvent This method notifies the Debug Manager in the Microsoft VM that a debugger program will be debugging a specific Java class. The debugger can specify a Java class name (for an applet or an application) or request interest in debugging all Java classes. The debugger can also specify interest in Java classes run in a specific host Win32 process or any Win32 process.

Once an interface pointer to IRemoteDebugManager object has been obtained, the debugger program must call the RegisterCallback method on this interface. The following code illustrates registering a callback in a sample Initialize method of a Java debugger class.

// Initialize is passed. The interface pointer to
//    IRemoteDebugManager is called.
HRESULT JavaDebugger::Initialize(IRemoteDebugManager *pirdm)
{
    HRESULT hr;

    // Register this JavaDebugger's IRemoteDebugManagerCallback with the
    // debug manager so it can be notified when new processes are run.

    hr = pirdm->RegisterCallback(this);

    if (hr == S_OK) {
        m_pirdm = pirdm;
        m_pirdm->AddRef();    // Increment the reference count. 
    }
    return(hr);
}

Once a debugger has registered its callback interface, it can request that it be notified when new Java processes are started. The debugger calls the RequestCreateEvent method of the IRemoteDebugManager interface to request being informed when the Microsoft VM creates new Java processes. The RequestCreateEvent method takes two parameters that allow the debugger to register to receive notifications of all new processes created, or in a specific process (a particular Java class) when it is created within a particular Win32 process. There are four possible combinations of these two parameters. The debugger can pass –1 for the process ID registering to receive notifications for any Win32 process. Any other value for the dwProcessID parameter indicates a specific Win32 process. The debugger can pass a zero-length string for the process name (Java class name) registering to receive notification of any Java process that is started. Any other value for the pcszProcessName parameter indicates a specific Java class name passed as a Unicode string.

The sample code below illustrates registering an interest to receive all process create events.

// Ask the debug manager to notify us when any Java class is run.
HRESULT hr;
DWORD dwProcessID = -1;             // For any Win32 process ID, 
                                    // use –1.
LPCOLESTR pcszProcessName = ""; // Zero-length string for all processes.

hr = m_pirdm->RequestCreateEvent(&pcszProcessName, dwProcessID);

At this point, a Java applet or application that is to be debugged can be started. If the Java application or applet was previously started using the Win32 CreateProcess function was in a suspended state, it can now be resumed. When any new Java processes are started, the debugger is notified through its IRemoteDebugManagerCallback interface.

Enumerating Active Java Processes

Using the RequestCreateEvent method of the IRemoteDebugManager object, a debugger can request to be informed of new Java processes that are created. A debugger program can also keep track of active processes by the calling GetActiveProcesses method on this object to retrieve a pointer to an enumerator object (IJavaEnumRemoteProcess) for all active Java processes. Two other registration interfaces, IJavaEnumRemoteProcess and IEnumRemoteProcess, can be used to enumerate all Java processes currently running in the Microsoft VM.

These interfaces implement the following methods that may be called by a debugger.

Method Description
Next Used to retrieve IRemoteProcess objects that represent active Java processes into an array. The number of Java processes to be retrieved is passed as one of the parameters; the enumeration pointer is incremented by that amount.
Skip Moves the position of the enumeration forward. The number of objects to be skipped is based on a parameter passed to the method.
Reset Sets or resets the positions the enumerator to the beginning of the list of Java processes.
Clone Copies a pointer to the current position in the list to another enumerator object.
GetNext Retrieves the next IRemoteProcess object being pointed to by the enumerator object and increments the enumeration pointer by one. Note that this method is only implemented by the IJavaEnumRemoteProcess object.

Registering with a Remote Process

Once a debugger has obtained a list of active Java processes—either through enumeration or from receiving ProcessCreateEvent method calls—it can attach to and debug a specific Java process.

To debug a specific process, a debugger program must first register a callback to receive notifications and information from the Microsoft VM regarding that process. The IRemoteProcess object, another registration interface, is used for this task.

The IRemoteProcess interface implements the following methods that can be called by a debugger.

Methods Description
RegisterCallback The debugger program calls this method to provide a callback that should receive notification and information regarding this active Java process. The debugger must pass an interface to its own COM object that implements IRemoteProcessCallback. This is the primary interface that the Microsoft VM communicates with the debugger. The VM sends information to the debugger regarding this process by calling various methods on this callback interface.
Detach The debugger program calls this method to detach its callback (IRemoteProcessCallback) that was attached by some previous call to RegisterCallback.
Break This method issues a break on all threads in this Java process, resulting in all threads being stopped. This method is asynchronous, so threads won't necessarily stop immediately.
GetGlobalContainerObject This method returns a pointer to an IRemoteContainerObject, representing the root of all objects in this Java process. This method is used by a debugger to collect static information on all class objects in a Java process.
FindClass This method finds a specific Java class. If the class isn't already loaded in the Java process, it’s loaded by the Microsoft VM.
TraceMethods This method enables or disables TraceEvent callbacks used for notification of method calls. It is being deprecated. Developers should use the newer Java Profiler interfaces.
GetThreadGroups This method returns an enumerator object (IJavaEnumRemoteThreadGroup) for all the thread groups in the Java process. The method is used by a debugger to collect dynamic information on all threads and class objects in a Java process.

Implementing Callback Notification Interfaces

For the Microsoft VM to communicate with a debugger, it registers with the Java Debug Manager and passes in pointers to COM objects that implement its notification interfaces. The Java debugger must implement two COM objects for this callback mechanism. The first provides global notification of new process creation. The second interface is used for debugging a specific Java process.

The notification interfaces that must be implemented by the debugger are as follows.

Notification Interfaces Description
IRemoteDebugManagerCallback This object is the initial callback through which the Microsoft VM communicates with the debugger. This callback must be registered by the debugger with the Java Debug Manager. This object has a single method that receives notification from the VM when new Java processes are created.
IRemoteProcessCallback This object is the primary callback through which the VM communicates with the debugger and passes notifications and information requested concerning a specific Java process.
IRemoteDebugManagerCallbackEx This COM object is not required to be implemented. This object inherits from and is a replacement for the IRemoteDebugManagerCallback object. This interface and is only necessary if the debugger wants to support JIT debugging.
IRemoteProcessCallbackEx This COM object is not required to be implemented. This object is a replacement for the IRemoteProcessCallback object and is only necessary if the debugger wants to receive notification of the class for which the Microsoft VM was started.

A debugger will normally implement either the IRemoteDebugManager interface or the IRemoteDebugManagerEx interface, which extends the former interface by adding one new method. Under normal circumstances, JIT debugging is disabled when a Java process is being debugged. The IRemoteDebugManagerEx interface is only used when the debugger wants to receive notification of the classes for which the Microsoft VM started to support JIT debugging.

When the debugger program starts execution, it must register with the Java Debug Manager in the VM passing its own callback interface pointer to IRemoteDebugManagerCallback (or IRemoteDebugManagerCallbackEx).

The IRemoteDebugManagerCallback and IRemoteDebugManagerCallbackEx interfaces implement the following methods that may be called by the Microsoft VM.

Method Description
ProcessCreateEvent Notifies the debugger that a new Java process has been created and passes back a pointer to the IRemoteProcess object for this new Java class.
StartClassEvent Only implemented by the IRemoteDebugManagerEx object. Notifies the debugger regarding the Java class it has started that the VM was started. For example, if the VM was started with JView using the command line “JView Hello,” the start class would be Hello. This method is only used for JIT debugging.

When a Java process starts in the Microsoft VM, the debugger will be notified through its ProcessCreateEvent method that a new Java process has been created. If the debugger decides to, it can register to receive notifications regarding this specific Java process. The IRemoteProcessCallback (or the IRemoteProcessCallbackEx) object is the primary way the Microsoft VM communicates with the debugger about a specific Java process. This callback has a large number of methods that must be implemented by the debugger.

A debugger will normally implement either the IRemoteProcessCallback or the IRemoteProcessCallbackEx interface (which extends the former interface by adding one new method). The Microsoft VM senses which interface the debugger supports by calling QueryInterface on the callback object passed to IRemoteProcess::RegisterCallback.

The IRemoteProcessCallback and the IRemoteProcessCallbackEx interfaces implement the following methods that may be called by the Microsoft VM.

Method Description
DebugStringEvent Notifies the debugger when the Java process being debugged outputs a string.
CodeBreakPointEvent Notifies the debugger when a code breakpoint is hit by the Java process being debugged.
DataBreakPointEvent Notifies the debugger when a data breakpoint is hit by the Java process being debugged.
ExceptionEvent Notifies the debugger when an exception occurs in the Java process being debugged.
StepEvent Notifies the debugger when an execution step completes in the Java process being debugged.
CanStopEvent Notifies the debugger during a range step when the Java process being debugged makes a function call.
BreakEvent Notifies the debugger when an asynchronous break occurs in response to the debugger calling IRemoteProcess:Break.
ThreadCreateEvent Notifies the debugger when a thread is created.
ThreadDestroyEvent Notifies the debugger when a thread is destroyed.
ThreadGroupCreateEvent Notifies the debugger when a thread group is created.
ThreadGroupDestroyEvent Notifies the debugger when a thread group is destroyed.
ClassLoadEvent Notifies the debugger when a Java class is loaded and indicates the thread on which the class was loaded.
LoadCompleteEvent Notifies the debugger when all Java class have been loaded.
ClassUnloadEvent Notifies the debugger when a Java class is unloaded.
TraceEvent Notifies the debugger while tracing is enabled when a method is entered in a Java class. This method is being deprecated. Developers should use the newer Java Profiler interfaces.
ProcessDestroyEvent Notifies the debugger when a Java process terminates. No further notifications are sent to the debugger regarding this Java process after this method is called.
StartClassEvent Only implemented by the IRemoteDebugManagerEx object; notifies the debugger regarding the Java class it has started. This method is only used for JIT debugging.

After a debugger registers an interest in a particular Java process (IRemoteProcess), it will begin to receive a large number of calls to its LoadClassEvent method for each class that was loaded before the debugger was attached. The debugger might receive a flurry of over 100 calls for a typical Java process. These notifications to the debugger are initially made asynchronously by the Microsoft VM. After notifications are made for all the currently loaded classes, a LoadCompleteEvent is received. After this notification, any other ClassLoadEvent notifications are sent synchronously for the thread that caused the class to be loaded.

If the debugger returns S_OK from a ClassLoadEvent method, this Java process is suspended and class loading by the Microsoft VM becomes synchronous. The execution of the Java process can be resumed once the debugger calls IRemoteThread::Go. If the debugger returns S_FALSE from each ClassLoadEvent call, the process of loading Java classes continues.

All these callback methods implemented by the debugger use the same return values. If the debugger returns S_FALSE, execution of the Java process continues. If the debugger returns S_OK, the Java process is suspended. This process can be resumed once the debugger calls IRemoteThread::Go.

The IRemoteProcess:FindClass method can be used to force a class to be loaded into the Microsoft VM if it is not already loaded. This method has side effects and the debugger will receive ClassLoadEvent method calls. The initializer for the Java class may also run and the debugger will not receive events during execution of the initializer. For example, if an exception occurs in the initializer, the debugger won't receive an exception event.

Thread groups are used to group threads together. Thread groups have special meaning for security purposes. Each Java applet is given its own thread group, and the applet can only manipulate threads within that group. These thread groups may be used to differentiate threads between multiple applets.

The debugger will receive notifications for a large number of events. The debugger is notified when thread groups and individual threads are created and destroyed. Threads are used extensively to get dynamic information when debugging a Java applet or application.

The debugger will also receive notifications on breakpoint and step events. The debugger sets breakpoints and controls execution by calling methods on the execution control interfaces. The objects to control execution control are also based using threads. In this case, threads are used to retrieve stack frames, calling frames and program counters.

Retrieving Static Information

Static information on a Java process is available through the IRemoteField hierarchy of interfaces. These interfaces represent fields that are members of classes. These fields can be methods, objects, inner classes, or nested class definitions. Because all the attributes of a field are constant during the lifetime of the field, this information can be cached by the debugger.

Global classes (classes not defined within other classes) can be thought of as fields of a global class. Access to static information in a Java process is based on using the IRemoteClassField and thread passed on each ClassLoadEvent notification to the debugger. The IRemoteProcess:GetGlobalContainerObject method (one of the interfaces used for retrieving dynamic information) can also be used to access the root of this object hierarchy and descend down it to retrieve IRemoteClassField objects.

The static information interfaces consist primarily of the IRemoteField interface and a collection of other interfaces designed for a specific Java object (primitive data types, arrays, classes, methods, and so on) that inherit from IRemoteField or from other interfaces that extend IRemoteField. The static information interfaces implemented by the Microsoft VM are as follows.

Static Information Interfaces Inherits From Description
IRemoteField IUnknown This object represents a field in a Java process.
IRemoteDataField IRemoteField This object represents a field that is not a method or a class definition. This interface inherits from IRemoteField. This interface is not used except as a base interface for IRemoteArrayField.
IRemoteArrayField IRemoteDataField This object represents arrays (special data fields). The only major difference between data and arrays (IRemoteDataField and IRemoteArrayField) is that arrays have a size. This interface inherits from IRemoteDataField.
IRemoteContainerField IRemoteField The object represents fields that contain other fields. This interface inherits from IRemoteField.
IRemoteClassField IRemoteContainerField This object represents a class definition. This interface inherits from IRemoteContainerField.
IRemoteClassFieldEx IRemoteClassField This object represents a class definition. This interface inherits from IRemoteClassField and adds one new method.
IRemoteInnerClassField IRemoteClassFieldEx This objects represents an inner class definition. This interface inherits from IRemoteClassFieldEx and adds several new method.
IRemoteMethodField IRemoteContainerField This object represents a method within a class. This interface inherits from IRemoteContainerField.
IEnumRemoteField IUnknown This object allows a debugger to enumerate fields in a Java process running in the Microsoft VM.
IJavaEnumRemoteField IEnumRemoteField This object extends the IEnumRemoteField interface (adds one new method) and allows a debugger to enumerate fields in a Java process running in the Microsoft VM.
IEnumLINEINFO IUnknown This object enumerates line number information for a method.

Fields are classified and defined by the FIELDKIND enum as follows:

FIELDKIND enum Value Description
FIELD_KIND_DATA_OBJECT 0x0001 A class instance.
FIELD_KIND_DATA_PRIMITIVE 0x0002 A primitive Java data type.
FIELD_KIND_ARRAY 0x0004 An array.
FIELD_KIND_CLASS 0x0008 A Java class.
FIELD_KIND_METHOD 0x0010 A Java class method.
FIELD_KIND_LOCAL 0x1000 A local variable in a Java method.
FIELD_KIND_PARAM 0x2000 A parameter passed to a Java method.
FIELD_KIND_THIS 0x4000 A THIS pointer to an object.
FIELD_KIND_INNER_CLASS 0x8000 An Java inner class.

If a field is not FIELD_KIND_LOCAL, FIELD_KIND_PARAM, or FIELD_KIND_THIS, it may be a class field or an array element. This may be determined by getting the kind of the field’s container. For an array element, the container field is FIELD_KIND_ARRAY. For a class field, the container field is FIELD_KIND_CLASS.

The following Java code sample illustrates the FIELDKINDs for a sample Java class.

class <globals>                           // FIELD_KIND_CLASS
{
    class FooClass                        // FIELD_KIND_CLASS
   {
       boolean bDone;                     // FIELD_KIND_DATA_PRIMITIVE
       class BarClass                     // FIELD_KIND_CLASS
      {
           String username[20];           // FIELD_KIND_ARRAY
      }
      BarClass mybar;                     // FIELD_KIND_DATA_OBJECT
      int BarMethod();                    // FIELD_KIND_METHOD
    };
};

Fields also have a set of modifiers contained in a flag attribute bitmask. These modifier bits are the same as those used in the access_flags field of the class file header. These bitmasks are defined in Java Virtual Machine specification published by JavaSoft.

These modifier bits are defined by the FIELD_ACC enum as follows:

FIELDMODIFIERS enum Value Description
FIELD_ACC_PUBLIC 0x0001 Is public and may be accessed from outside its package (visible to everyone). This modifier can be applied to any class, interface, field, or method.
FIELD_ACC_PRIVATE 0x0002 Is private and usable only within the defining class. This modifier can be applied to a class, method, or class field.
FIELD_ACC_PROTECTED 0x0004 Is protected and may be accessed within this class and subclasses. This modifier can be applied to any class, method, or class field.
FIELD_ACC_STATIC 0x0008 A static field or method. This modifier can be applied to any class, method, or field.
FIELD_ACC_FINAL 0x0010 Is final and no further subclassing or assignment is allowed. This modifier can be applied to any class, method, or field.
FIELD_ACC_SYNCHRONIZED 0x0020 Use monitor lock when the method is invoked. This modifier can be applied to any class or method.
FIELD_ACC_VOLATILE 0x0040 The value of this field cannot be cached. This modifier can be applied to any class field.
FIELD_ACC_TRANSIENT 0x0080 This field cannot be read or written by a persistent object manager. This modifier can be applied to any class field.
FIELD_ACC_NATIVE 0x0100 This method is implemented using native code. This modifier can be applied to any class or method.
FIELD_ACC_INTERFACE 0x0200 Is an interface (used to distinguish between an interface and a class). This modifier is applied to an interface.
FIELD_ACC_ABSTRACT 0x0400 An abstract class or interface that may not be instantiated. This modifier can be applied to a class, an interface, or a method.
FIELD_ACC_SUPER 0x0800 Treat superclass methods specially in invokespecial (used for backward compatibility). This modifier can be applied to any class or interface.
FIELD_ACC_SYNTHETIC 0x1000 Set on fields that the compiler had to generate (used by inner classes).

The IRemoteField interface and the other IRemoteXXXField interfaces that inherit from IRemoteField implement a standard set of methods used to get the name, kind, type, and modifiers of a field as well as the field representing the class that contains the field. The GetContainer method provides a way for a debugger to maneuver up the field hierarchy in a class.

The following methods of IRemoteField (and the objects that inherit from it) can be called by a debugger.

Methods Description
GetName Returns the identifier (the class, variable, or method name) for this field.
GetKind Returns the kind (FIELD_KIND enum) of this field.
GetType Returns an IRemoteField object that represents the type of this field. The relationship between a field and its type depends on the FIELD_KIND of the field. The type will be either a class type or a Java native object type (boolean, short, integer, long, and so on). When this method is called on a global container field, the method returns S_OK and IRemoteField object returned representing the type is NULL.
GetContainer Returns the field representing the class that contains the field.
GetModifiers Returns a bitmask of flags containing the modifiers (FIELDMODIFIERS enum) for this field. If a bit is set, the type is modified in that way.

The following methods are specific to the interfaces that inherit from IRemoteField and can be called by a debugger.

Methods Description
GetSize Returns the number of elements in an array. This method is implemented only by the IRemoteArrayField interface.
GetFields Returns an enumerator (IJavaEnumRemoteField) for the fields that are contained by this field and match given characteristics. The characteristics are determined by three parameters passed to the method that specify the name of the field, the modifiers bitmask, and the kind. A null parameter passed for the name is used to include all names. A bitmask of 0 is used to include all modifiers. A FIELD_KIND of 0 is used to include all kinds. This method is implemented only by the IRemoteContainerField, IRemoteClassField, IRemoteClassFieldEx, IRemoteInnerClassField, and the IRemoteMethodField interfaces.
GetFileName Returns the full name of the class if it is available (C:\classes\HelloWorld.class, for example). This method is implemented only by the IRemoteClassField, IRemoteClassFieldEx, and IRemoteInnerClassField interface.
GetSourceFileName Returns the name of the source file attribute (SourceFile) from the class file if it is available (HelloWorld.java, for example). This method is implemented only by the IRemoteClassField, IrRemoteClassFieldEx, and IRemoteInnerClassField interfaces.
GetSourceFileDir Returns the name of the source file directory attribute (SourceDir) from the class file if it is available. This method is implemented only by the IRemoteClassFieldEx and the IRemoteInnerClassField interfaces.
GetSuperclass Returns the class (an IRemoteClassField) from which this class is derived. For Java.Lang.Object, the top of the hierarchy, this method returns NULL. This method is implemented only by the IRemoteClassField interface.
GetInterfaces Returns an enumerator (IJavaEnumRemoteField) for the interfaces that this class implements. If the class has no interfaces, an enumerator is returned that enumerates nothing. This method is implemented only by the IRemoteClassField, IRemoteClassFieldEx, and IRemoteInnerClassField interface.
GetConstantPoolItem Returns the raw contents for the constant pool and is used for disassembly. Any indices contained within the CP item are converted from big endian order to platform byte order. This method is implemented only by the IRemoteClassField, IRemoteClassFieldEx, and IRemoteInnerClassField interface.
GetIndexedField Obtains a local variable or parameters field from a method by local variable index and byte offset.

The constant pool items are defined by an initial tag byte that indicates the format of the item stored followed the specific information for that constant entry. The constant pool tag bytes are defined as follows:

enum Value Description
CP_CONSTANT_UTF8 1 A UCS Transformation Format (UTF-8) string used to represent constant string values encoded in a structure with a 2-byte length preceding the string.
CP_CONSTANT_UNICODE 2 A Unicode string with a two-byte length preceding the string.
CP_CONSTANT_INTEGER 3 A 32-bit integer constant.
CP_CONSTANT_FLOAT 4 A 32-bit single-precision floating point constant.
CP_CONSTANT_LONG 5 A 64-bit long constant.
CP_CONSTANT_DOUBLE 6 A 64-bit double precision floating-point constant.
CP_CONSTANT_CLASS 7 A 16-bit index to a UTF-8 constant name.
CP_CONSTANT_STRING 8 A 16-bit index to a UTF-8 constant string.
CP_CONSTANT_FIELDREF 9 A 16-bit index to a class followed by a 16-bit index to a name_and_type.
CP_CONSTANT_METHODREF 10 A 16-bit index to a class followed by a 16-bit index to a name_and_type.
CP_CONSTANT_
INTERFACEMETHODREF
11 A 16-bit index to a class followed by a 16-bit index to a name_and_type.
CP_CONSTANT_NAMETYPE 12 One 16-bit index to a name (UTF-8 constant) followed by a 16-bit index to a field or method descriptor (a UTF-8 constant) representing the type of a class or instance variable. The field or method descriptor is a series of characters defined in the Java Virtual Machine specification published by Sun Microsystems.

The following methods are specific to the IRemoteInnerClassField and can be called by a debugger.

Methods Description
GetInnerClassName Returns the real class name, not the mangled class name from the Java compiler.
GetInnerClassModifiers Returns the real field modifiers for the inner class.
GetOuterClass Returns an IRemoteClassField representing the outer class.

The IRemoteMethodField, which inherits from the IRemoteContainerField, represents a method within a class. This interface implements a number of methods that can be used by a debugger to set and clear breakpoints, get line number info, return Java bytecodes, and other information.

The following methods are specific to the IRemoteMethodField and can be called by a debugger.

Methods Description
SetBreakpoint Sets a code breakpoint at a given byte offset from the start of a method. The VM will not validate the given location of the breakpoint; a breakpoint may be set at any offset within the method’s bytecodes. Breakpoints are reference counted and may be set multiple times at the same byte offset.
ClearBreakpoint Clears a code breakpoint at a given byte offset from the start of a method. This method will only clear breakpoints set by SetBreakpoint. If a breakpoint is set multiple times, it must be cleared the same number of times to eliminate it completely.
GetLineInfo Returns an enumerator of LINEINFO structures (IJavaEnumLINEINFO objects) describing the mapping between source lines and byte offset within the Java bytecodes representing the method. This mapping is in order of increasing offsets. The last element in the list is a “dummy” node with a line number field set to the last line of the method + 1 and the offset field set to the last offset in the method +1.
GetBytes Returns an interface (ILockBytes) that can be used to access the Java bytecode of the method. This method can be used by a debugger to display a disassembly of the bytecode.
GetScope Returns the range of byte offsets (within which the object is in scope) that can be used by a debugger to obtain the value of some field within this method.
GetIndexedField Obtains a local variable or parameters field from a method by local variable index and byte offset.

Enumerating Static Fields

Several of the interfaces that inherit from the IRemoteField object (IRemoteContainerField, IRemoteClassField, and IRemoteMethodField) implement a GetFields method that returns an enumerator for the fields contained by this field. Two other static information interfaces, IJavaEnumRemoteField and IEnumRemoteField, can be used to enumerate all these fields contained within a class, method, or container. The IJavaEnumRemoteField object inherits from IEnumRemoteField, extending this interface with one additional method.

These interfaces implement the following methods that may be called by a debugger.

Method Description
Next Used to retrieve IRemoteField objects that represent fields. The number of fields to be retrieved is passed as one of the parameters; the enumeration pointer is incremented by that amount.
Skip Moves the position of the enumeration forward. The number of objects to be skipped is based on a parameter passed to the method.
Reset Sets or resets the positions the enumerator to the beginning of the list of fields.
Clone Copies a pointer to the current position in the list to another enumerator object.
GetCount Returns the number of fields being pointed to by the enumerator object.
GetNext Retrieves the next IRemoteField object being pointed to by the enumerator object and increments the enumeration pointer by one. Note that this method is only implemented by the IJavaEnumRemoteField object.

Enumerating Line Number Information

Line number information represents the mapping between Java source code line numbers and byte offsets in the method. This information is represented as an array of LINEINFO structures maintained for each method. The IEnumLINEINFO interface provides access to this information.

The IEnumLINEINFO interface implements the following methods that may be called by a debugger.

Method Description
Next Used to retrieve LINEINFO structures that represent the mapping between Java source code line numbers and byte offset in the method. The number of LINEINFO structures to be retrieved is passed as one of the parameters; the enumeration pointer is incremented by that amount.
Skip Moves the position of the enumeration forward. The number of LINEINFO structures to be skipped is based on a parameter passed to the method.
Reset Sets or resets the positions the enumerator to the beginning of the list of LINEINFO structures.
Clone Copies a pointer to the current position in the list to another enumerator object.
GetNext Retrieves the next LINEINFO structure being pointed to by the enumerator object and increments the enumeration pointer by one. Note that this method is only implemented by the IJavaEnumLINEINFO object.
GetCount Returns the number of fields being pointed to by the enumerator object. Note that this method is only implemented by the IJavaEnumLINEINFO object.

Retrieving Dynamic Information

Dynamic information on a Java process is available through the IRemoteObject hierarchy of interfaces. These interfaces provide bound access to objects of different types. An object does not necessarily refer to an instance of a class, but represents an instance of any type. The information obtained from an IRemoteObject is only valid during the lifetime of the actual object that it represents. Consequently, dynamic information cannot be cached by the debugger.

Access to dynamic information in a Java process is based on using the IRemoteThreadGroup and IRemoteThread passed on each ThreadGroupCreateEvent and ThreadCreateEvent notification to the debugger. The IRemoteProcess:GetGlobalContainerObject method can also be used to access the root of this object hierarchy and descend down it to retrieve IRemoteClassField objects.

The dynamic information interfaces consist primarily of the IRemoteObject, IEnumRemoteObject, and the IEnumRemoteValue interfaces and a collection of other interfaces designed for a specific Java object (primitive data types, arrays, or classes) that inherit from IRemoteObject or IEnumRemoteValue. The dynamic information interfaces implemented by the Microsoft VM are as follows.

Dynamic Information Interfaces Inherits From Description
IRemoteObject IUnknown Represents bound access to objects of different types in a Java process.
IRemoteBooleanObject IRemoteObject Provides run-time access to the value of a boolean variable.
IRemoteByteObject IRemoteObject Provides run-time access to the value of a byte variable.
IRemoteCharObject IRemoteObject Provides run-time access to the value of a char variable.
IRemoteContainerObject IRemoteObject Provides run-time access to container objects.
IRemoteClassObject IRemoteContainerObject Provides run-time access to class objects.
IRemoteDoubleObject IRemoteObject Provides run-time access to the value of a double variable.
IRemoteFloatObject IRemoteObject Provides run-time access to the value of a float variable.
IRemoteIntObject IRemoteObject Provides run-time access to the value of an int variable.
IRemoteLongObject IRemoteObject Provides run-time access to the value of a long variable.
IRemoteShortObject IRemoteObject Provides run-time access to the value of a short variable.
IRemoteArrayObject IRemoteObject Provides run-time access to array objects.
IEnumRemoteObject IUnknown Allows a debugger to enumerate objects in a Java process running in the Microsoft VM.
IEnumRemoteValue IUnknown Allows a debugger to enumerate the value of a variable in a Java process running in the Microsoft VM.
IEnumRemoteBooleanValue IEnumRemoteValue Enumerates boolean values.
IEnumRemoteByteValue IEnumRemoteValue Enumerates byte values.
IEnumRemoteCharValue IEnumRemoteValue Enumerates char values.
IEnumRemoteDoubleValue IEnumRemoteValue Enumerates double values.
IEnumRemoteFloatValue IEnumRemoteValue Enumerates float values.
IEnumRemoteIntValue IEnumRemoteValue Enumerates int values.
IEnumRemoteLongValue IEnumRemoteValue Enumerates long values.
IEnumRemoteShortValue IEnumRemoteValue Enumerates short values.
IJavaEnumRemoteValue IEnumRemoteValue Allows a debugger to enumerate the value of a variable in a Java process running in the Microsoft VM.
IJavaEnumRemoteBooleanValue IJavaEnumRemoteValue Enumerates boolean values.
IJavaEnumRemoteByteValue IJavaEnumRemoteValue Enumerates byte values.
IJavaEnumRemoteCharValue IJavaEnumRemoteValue Enumerates char values.
IJavaEnumRemoteDoubleValue IJavaEnumRemoteValue Enumerates double values.
IJavaEnumRemoteFloatValue IJavaEnumRemoteValue Enumerates float values.
IJavaEnumRemoteIntValue IJavaEnumRemoteValue Enumerates int values.
IJavaEnumRemoteLongValue IJavaEnumRemoteValue Enumerates long values.
IJavaEnumRemoteShortValue IJavaEnumRemoteValue Enumerates short values.

Java uses a number of built-in types that can be represented by a Win32 debugger written in C and C++ as a series of typedefs as follows:

// JAVA built-in types
    typedef BYTE JAVA_BOOLEAN;
    typedef signed char JAVA_BYTE;
    typedef USHORT JAVA_CHAR;
    typedef double JAVA_DOUBLE;
    typedef float JAVA_FLOAT;
    typedef LONG JAVA_INT;
    typedef LONGLONG JAVA_LONG;
    typedef SHORT JAVA_SHORT;
    typedef LPOLESTR JAVA_STRING;

The IRemoteObject interface and the other IRemoteXXXObject interfaces that inherit from IRemoteObject implement a standard set of methods used to get the type of an object, and set or clear data breakpoints on the object. The breakpoint will fire when the value of the object changes. For classes, a data breakpoint will fire when the object references a different instance of that class. For arrays, a data breakpoint will fire when the object references a different instance of the array (when one array is assigned or copied to another). The GetFieldObject method of the IRemoteContainerObject interface provides a way for a debugger to access fields in a container (class).

The following methods of IRemoteObject (and the objects that inherit from it) can be called by a debugger.

Methods Description
GetType Returns the type of the object (an IRemoteField object). A debugger would normally then call the GetKind method of the IRemoteField interface to determine the FIELD_KIND of the object. The type will be either a class type or a Java native object type (boolean, short, integer, long, and so on.).
SetBreakpoint Sets a data breakpoint on the object. The breakpoint fires when the value of the object changes.
ClearBreakpoint Clears a data breakpoint on the object previously set with the SetBreakpoint method.
GetValue Gets the value of a primitive Java type. This method is implemented by the IRemotexxxObject interfaces that inherit from IRemoteObject, where xxx represents one of the primitive Java data types.
SetValue Sets the value of a primitive Java type. This method is implemented by the IRemotexxxObject interfaces that inherit from IRemoteObject, where xxx represents one of the primitive Java data types.

The following methods are unique to the IRemoteObjectEx and can be called by a debugger.

Methods Description
IsSameObject Indicates whether two objects are the same object.
GetContainer Returns an IRemoteObject that represents the container for the current object. This methods allows a debugger to navigate back up the hierarchy of objects.
GetIdentity Returns a new IRemoteObjectEx that is detached from its containers. This method is used for data breakpoints and allows a debugger to hang onto an object across execution.

The following method is unique to the IRemoteContainerObject (and the IRemoteClassObject that inherit from it) and can be called by a debugger.

Methods Description
GetFieldObject Returns an IRemoteObject that represents the object contained in the field of this object. The IRemoteField object that is returned is not bound to the instance of the object and can be used to extract the value of that field from many different IRemoteContainerObject in the same Java process. This method allows a debugger to navigate down the hierarchy of objects.

The following method is unique to the IRemoteClassObject and can be called by a debugger.

Methods Description
GetDerivedMostType Returns an IRremoteClassField that represents the object's derived-most type. An example of a derived-most type would be a MyException class derived from the java.io.IOException class.

Enumerating Dynamic Information

Several of the interfaces that inherit from the IRemoteObject object (IRemoteContainerObject and IRemoteClassObject) implement a GetFieldObject method that returns an object representing a specific field.

Several other dynamic information interfaces, IEnumRemoteObject, IEnumRemoteValue, and IJavaENumRemoteValue, can be used to enumerate objects and enumerate values. The IJavaEnumRemoteValue object inherits from IEnumRemoteValue, extending this interface with one additional method.

These interfaces implement the following methods that may be called by a debugger.

Method Description
Next Used to retrieve objects (IRemoteObject). The number of objects to be retrieved is passed as one of the parameters; the enumeration pointer is incremented by that amount.
Skip Moves the position of the enumeration forward. The number of objects to be skipped is based on a parameter passed to the method.
Reset Sets or resets the positions the enumerator to the beginning of the list of fields.
Clone Copies a pointer to the current position in the list to another enumerator object.
GetCount Returns the number of objects being pointed to by the enumerator object.
GetNext Retrieves the next LINEINFO structure being pointed to by the enumerator object and increments the enumeration pointer by one. Note that this method is only implemented by the IJavaEnumRemoteValue object and the interfaces that inherit from it.

Controlling Execution

Controlling execution of a Java process is available through the IRemoteThread and IRemoteStackFrame interfaces. These interfaces provide access to call stacks within the threads of the Java process being debugged. Each stack frame represents the state of execution within a method. Consequently, execution control information cannot be cached by the debugger.

Access to execution control information in a Java process is based on using the IRemoteThreadGroup and IRemoteThread passed on each ThreadGroupCreateEvent and ThreadCreateEvent notification to the debugger. The IRemoteProcess:GetGlobalContainerObject method can also be used to access the root of this object hierarchy and descend down it to retrieve IRemoteThreadGroup and IRemoteThread objects. These IRemoteThread objects can then be used to access the IRemoteStackFrame objects

The execution control interfaces consist primarily of the IRemoteStackFrame, IRemoteThread, and the IRemoteThreadGroup interfaces and a collection of other interfaces used for enumerating threads and thread groups. The execution control interfaces implemented by the Microsoft VM are as follows.

Execution Control Interfaces Inherits From Description
IRemoteStackFrame IUnknown Provides access to call stacks within the threads of the Java process being debugged. Each stack frame represents the state of execution within a method.
IRemoteStackFrameEx IRemoteStackFrame Provides access to call stacks within the threads of the Java process being debugged. Each stack frame represents the state of execution within a method. This interface inherits from IRemoteStackFrame and adds two new methods.
IRemoteThreadGroup IUnknown Provides access to thread groups.
IRemoteThreadGroupEx IRemoteThreadGroup Provides access to thread groups. This interface inherits from IRemoteThreadGroup and adds one new method.
IRemoteThread IUnknown Provides access to threads.
IRemoteThreadEx IRemoteThread Provides access to threads. This interface inherits from IRemoteThread and adds several new methods.
IEnumRemoteStackFrames IUnknown Allows a debugger to enumerate stack frames in a Java process running in the Microsoft VM.
IEnumRemoteThreadGroup IUnknown Allows a debugger to enumerate thread groups in a Java process running in the Microsoft VM.
IJavaEnumRemoteThreadGroup IEnumRemoteThreadGroup Allows a debugger to enumerate thread  groups in a Java process running in the Microsoft VM. This interface inherits from IEnumRemoteThreadGroup and adds one new method.
IEnumRemoteThread IUnknown Allows a debugger to enumerate threads in a Java process running in the Microsoft VM.
IJavaEnumRemoteThread IEnumRemoteThread Allows a debugger to enumerate threads in a Java process running in the Microsoft VM. This interface inherits from IEnumRemoteThread and adds one new method.

The IRemoteThreadGroup and the IRemoteThreadGroupEx interfaces implement a set of methods used to get the name of a thread group and enumerate the other thread groups and threads in a thread group.

The following methods of IRemoteThreadGroup (and the IRemoteThreadGroupEx objects that inherit from it) can be called by a debugger.

Methods Description
GetName Returns the name of this thread group.
GetThreads Returns an enumerator for the threads in this thread group.
GetThreadGroups Returns an enumerator for the thread groups in this thread group.
GetParent Returns the parent thread group of this thread group. This method is implemented by the IRemoteThreadGroupEx interface that inherits from IRemoteThreadGroup.

Enumerating Thread Groups, Threads, and Stack Frames

Two execution control interfaces, IJavaEnumRemoteThreadGroup and IEnumRemoteThreadGroup, can be used to enumerate all these thread groups contained in a Java process. The IJavaEnumRemoteThreadGroup object inherits from IEnumRemoteThreadGroup, extending this interface with one additional method.

The IRemoteThreadGroup interface implements a GetThreads method that returns an enumerator for the threads in this thread group. Two other execution control interfaces, IJavaEnumRemoteThread and IEnumRemoteThread, can be used to enumerate all the threads contained within a thread group. The IJavaEnumRemoteThread object inherits from IEnumRemoteThread, extending this interface with one additional method.

These interfaces implement the following methods that may be called by a debugger.

Method Description
Next Used to retrieve IRemoteThread  or IRemoteThreadGroup objects that represent thread groups or threads in a Java process. The number of objects to be retrieved is passed as one of the parameters; the enumeration pointer is incremented by that amount.
Skip Moves the position of the enumeration forward. The number of objects to be skipped is based on a parameter passed to the method.
Reset Sets or resets the positions the enumerator to the beginning of the list of fields.
Clone Copies a pointer to the current position in the list to another enumerator object.
GetNext Retrieves the next IRemoteThreadGroup or IRemoteThread object being pointed to by the enumerator object and increments the enumeration pointer by one. Note that this method is only implemented by the IJavaEnumRemoteThreadGroup and IJavaEnumRemoteThread object.

Controlling Execution with Remote Thread Objects

Execution of a Java process is controlled through methods implemented by the IRemoteThread and IRemoteThreadEx interfaces. Methods on these objects allow a debugger to suspend or resume execution of a thread, step through or over a method, and get the current stack frame on this thread. Other methods return the name of the thread and the thread group containing this thread, which allow a debugger to move up the hierarchy of thread objects.

For notification, many of these methods generate a StepEvent call to the debugger on its IRemoteCallBack or IRemoteCallbackEx interface. If StepEvent returns S_FALSE, execution continues. If StepEvent returns S_OK, execution of this thread is suspended until the Go or Resume method is called.

The following methods of IRemoteThread (and the IRemoteThreadEx object that inherits from it) can be called by a debugger.

Methods Description
GetName Returns the name of this thread.
GetCurrentStackFrame Returns the currently executing stack frame on this thread.
GetThreadGroup Returns the thread group (traverse up the hierarchy) that contains this thread.
Go Continues (resumes) execution of this thread. This method clears the execution state and returns immediately.
Step Steps a single instruction of bytecode. This method steps over method calls in a Java class. The StepEvent method exported by the debugger on the IRemoteCallback interface is called when execution is complete.
StepIn Steps over a single bytecode instruction. The StepIn method steps into method calls in a Java class. This method return immediately. The StepEvent method exported by the debugger on the IRemoteCallback interface is called when execution is complete.
StepOut Continues execution until the end of the current method. The next instruction to be executed is the first instruction after the call in the calling method. This method returns immediately. The StepEvent method exported by the debugger on the IRemoteCallback interface is called when execution is complete.
RangeStep Continues execution until the PC is outside the given range. The RangeStep method steps over method calls in a Java class. The StepEvent method (exported by the debugger on the IRemoteCallback interface) is called when execution is complete. If the flow of execution enters another method, the debugger receives a CanStopEvent method call on its IRemoteCallback interface.
RangeStepIn Continues execution until the PC is outside the given range. The RangeStep method steps into method calls in a Java class. The StepEvent method exported by the debugger on the IRemoteCallback interface is called at the first instruction of the stepped into method. If the debugger returns S_FALSE from StepEvent, the Microsoft VM continues executing to the end of this method, and continues executing within the given range. when execution is complete. If the flow of execution enters another method, the debugger receives a CanStopEvent method call on its IRemoteCallback interface.
Destroy Destroys a thread. The ThreadDestroy method exported by the debugger on the IRemoteCallback interface is called when the operation is complete.
Suspend Suspends execution of this thread.
Resume Resumes execution of this thread.
GetSuspendCount Returns a count of how many times the debugger called Suspend.
GetThreadID Returns the actual Win32 thread ID for the thread. This method is implemented by the IRemoteThreadEx interface.
GetStackFrames Returns an enumerator for all of the stack frames in this thread. This method is implemented by the IRemoteThreadEx interface.
IsStartBlock Indicates if a given stack frame is at the top of the thread (the current stack frame). This method is implemented by the IRemoteThreadEx interface.
WatchForStep This method is used for cross-language engine support (JavaScript and Microsoft® Visual Basic® Scripting Edition, for example) to watch for stepping above or below a given stack pointer. This method is implemented by the IRemoteThreadEx interface.
Continue Continues (resumes) execution of this thread similar to the Go method, but leaves the Java process in step mode. This call returns immediately. This method is implemented by the IRemoteThreadEx interface.
AllowExecution This method is used to control whether execution of this thread should be enabled or disabled. This method is used for function evaluation. This method is implemented by the IRemoteThreadEx interface.
PassExceptionToDebuggee This method is used to control how exceptions are handled during an ExceptionEvent. If this method is called with FALSE as the parameter, the Microsoft VM “swallows” any exceptions that occur, ignores the exception that just occurred, and continues execution. If this method is called with TRUE as the parameter, exception handling occurs normally. If an exception is not caught by the Java process, the exception is passed to the Microsoft VM and the Java process is aborted and the thread is terminated. This method is implemented by the IRemoteThreadEx interface and may only be called during an ExceptionEvent.
ClearExecutionState This method clears the execution state and returns immediately. Executing a Go method is the equivalent of a ClearExecution method call followed by a Continue call. This method is implemented by the IRemoteThreadEx interface.

Accessing Call Stacks

Call stacks are accessed through methods implemented by the IRemoteThread and IRemoteStackFrame and the IRemoteStackFrameEx interfaces. Stack frames can be enumerated by calling the GetStackFrames method of the IRemoteThreadEx interface. The current stack frame can be returned by calling the GetCurrentStackFrame method of the IRemoteThread or the IRemoteThreadEx interfaces.

Methods on these objects allow a debugger to view and change bytecodes that are about to be executed. Other methods return the calling frame and the method object, which allow a debugger to navigate up the hierarchy of objects.

The following methods of IRemoteStackFrame (and the IRemoteStackFrameEx object that inherits from it) can be called by a debugger.

Methods Description
GetCallingFrame Returns the stack frame representing the caller of this method.
GetMethodObject Returns an IRemoteContainer object representing the instance of the method object.
GetPC Returns the byte offset from the start of this method of the next instruction to be executed. In non-topmost stack frames, this returns the byte offset of the invoke instruction that is being executed.
SetPC Sets the byte offset from the start of this method of the next instruction to be executed.
GetKind Returns the FRAMEKIND of this frame stack.
GetStackRange Returns the real Win32 pointers top the upper and lower bounds to a stack frame. This method is used for mixed language debugging, so the debugger can order the call stack. This method is implemented by the IRemoteStackFrameEx interface.
GetRealPC Returns the return address for the stack frame (real PC byte offset from the start of this method) of where execution will resume. This method is implemented by the IRemoteStackFrameEx interface.

Top © 1998 Microsoft Corporation. All rights reserved. Terms of use.