Debugging Java



CL-JDI defines an interface mirroring Java virtual machine state.  The library includes an implementation of the Java Debug Wire Protocol (JDWP).  CL-JDI is written in Common Lisp, but tries to follow Sun's Java Debug Interface (JDI) in its organization.

CL-JDI was written by David Lichteblau and is available under the terms of the GNU General Public License.

There is a (prototype) GUI debugger called Decaf based on this library.

Getting Started

To enable a JDWP listener in Sun's virtual machine implementation, a suitable -Xrunjdwp option must be passed at startup. Example:

$ java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8000 Foo
With this option, the virtual machine will suspend execution before the initial class runs.  Connect to the virtual machine using JDI:JDWP-CONNECT and inspect the virtual machine mirror like this:
(jdi:with-virtual-machine (vm (jdi:jdwp-connect "localhost" 8000))
  (print (jdi:all-classes vm))
This examples uses JDI:WITH-VIRTUAL-MACHINE to automatically close the JDWP connection after completion.

Another example is given in the section on event handling.

Error handling

Condition Class JDI:JDWP-ERROR
Function JDI:JDWP-ERROR-CODE (condition)
Macro JDI:JDWP-HANDLER-CASE (form &rest cases)
All functions described here can signal condition jdi:jdwp-error.  Error codes are named by keyword symbols.  (See also:
Error Constants in the JDWP specification.)

fixme: We might need to signal non-JDWP-errors and define our own condition hierarchy.

Virtual Machine Mirrors

JDI:VIRTUAL-MACHINE mirrors a virtual machine.  The mirror can be closed explicitly using JDI:DISPOSE.

Connect to the JDWP server at the given TCP address and return a virtual machine mirror representing the connection.

Macro JDI:WITH-VIRTUAL-MACHINE ((var vm) &body body) => result
Bind VAR to the value of VM, then execute BODY as an implicit PROGN.  Automatically close VM on exit from BODY.

Virtual Machine Methods

Function JDI:ALL-CLASSES (virtual-machine) => list of JDI:REFERENCE-TYPE
Return a list of all reference types current loaded, including array and interface types.

Function JDI:ALL-THREADS (virtual-machine) => list of JDI:THREAD
Return a list of threads running in the virtual machine.

Function JDI:BASE-DIRECTORY (virtual-machine) => STRING
Return the home directory of the virtual machine as a string.  Directory names returned by JDI:CLASS-PATH JDI:BOOSTRAP-CLASS-PATH are specified relative to this directory.

Function JDI:BOOTSTRAP-CLASS-PATH (virtual-machine) => list of STRING
Return the virtual machine's bootstrap class path as a list of directory names.

Function JDI:CLASS-PATH (virtual-machine) => list of STRING
Return the virtual machine's class path as a list of directory names.

Function JDI:DESCRIPTION (virtual-machine) => STRING
Return a description of the virtual machine as a string.

Function JDI:DISPOSE (virtual-machine)
Close the virtual machine mirror.  In the case of a JDWP client, close the JDWP connection.  (
JDWP definition)

Function JDI:EXIT (virtual-machine return-code)
Terminate the virtual machine.  (JDWP definition)

Function JDI:GET-CAPABILITY (virtual-machine capability) => BOOLEAN
Determine whether the virtual machine has the given capability.  Capabilities are named by keywords.  Example:
(full list of JDWP capabilities)

Function JDI:JDWP-VERSION (virtual-machine) => (major . minor)
Return the JDWP version implemented by the virtual machine as a cons of two integers, the major and minor version number.

Function JDI:READ-EVENT-SET (virtual-machine &key wait) => JDI:EVENT-SET
Read an event set from the virtual machine's event queue and return it.  Optionally wait for events to arrive first.  If WAIT is not given and no events have been received, return NIL.

Function JDI:RESUME (virtual-machine)
"Resume" all threads in the virtual machine.  (JDWP definition)

Function JDI:SUSPEND (virtual-machine)
"Suspend" all threads in the virtual machine.  (JDWP definition)

Function JDI:VERSION (virtual-machine) => STRING
Return a description of the virtual machine's version as a string.

Reference Types

Instances of JDI:REFERENCE-TYPE represent Java "classes" (proper classes, array classes, and interfaces) loaded into the virtual machine.  A list of all classes can be retrieved using the virtual machine method JDI:ALL-CLASSES.

Reference Type Methods

Function JDI:FIELDS (class) => list of JDI:FIELD
Function JDI:ALL-FIELDS (class) => list of JDI:FIELD
Return the list of fields declared in this class.  In the case of JDI:ALL-FIELDS, include fields declared in superclasses and -interfaces.

Function JDI:FIELD-VALUE (field class) => value
Function JDI:FIELD-VALUES (fields class) => list of values
Determine the value or values of the specifed static fields.

Function JDI:METHODS (class) => list of JDI:METHOD
Function JDI:ALL-METHODS (class &key exclude-overridden) => list of JDI:METHOD
Return the list of methods declared in this class.  In the case of JDI:ALL-METHODS, include methods declared in superclasses and -interfaces.  If EXCLUDE-OVERRIDDEN is true, return for each pair of method name and signature only the most specific declaration, excluding overridden definitions from superclasses.

Function JDI:INTERFACES (class) => list of JDI:INTERFACE-TYPE
Return the list of interfaces implemented by this class.

Function JDI:NAME (class) => STRING
Return the class name.  Examples: com.acme.Foo, com.acme.Foo[], int[].

Function JDI:SIGNATURE (class) => STRING
Return the JNI class name.  Examples: Lcom/acme/Foo;, [Lcom/acme/Foo;, [I.

Function JDI:SOURCE-FILE (class) => STRING
Return the name the source file this class was compiled from.  The returned name does not include the file's directory.

Return this class's superclass.  Note: This function is not defined for interface types.

Array Type Methods

Function JDI:COMPONENT-SIGNATURE (array-class) => STRING
Return the array element type's JNI signature (examples: Lcom/acme/Foo;, I).

Return the array element type.  fixme: This currently returns NIL in the case of primitive types.

Function JDI:COMPONENT-TYPE-NAME (array-class) => STRING
Return the array element type's name (examples: com.acme.Foo, int).

Class Type Methods

Function JDI:SUBCLASSES (class) => list of JDI:REFERENCE-TYPE
Return the list of all currently loaded subclasses of this class.

Interface Type Methods

Return the list of all currently loaded subinterfaces of this interface class.

Class Members


Member Methods

Return the class or interface type this member was defined in.

Function JDI:NAME (member) => STRING
Return this member's name.

Function JDI:SIGNATURE (member) => STRING
Return this member's signature.  Examples: Ljava/lang/String; (for a field), (IJZ)V (for a method).

Function JDI:PRIVATEP (member) => BOOLEAN
Function JDI:PROTECTEDP (member) => BOOLEAN
Function JDI:PUBLICP (member) => BOOLEAN
Function JDI:FINALP (member) => BOOLEAN
Function JDI:SYNTHETICP (member) => BOOLEAN
Function JDI:TRANSIENTP (member) => BOOLEAN
Function JDI:VOLATILEP (member) => BOOLEAN
Function JDI:ABSTRACTP (member) => BOOLEAN
Function JDI:NATIVEP (member) => BOOLEAN
Test the member's access flags for the appropriate bit.

Method Methods

Function JDI:ARGUMENT-TYPE-NAMES (method) => list of STRING
Return the JNI names of this method's argument types.

Try to guess this method's local variables from its signature.  This function is helpful for classes without debugging information.  Be warned that local variable information returned by this function is unreliable.

Return this method's local variables.  Note: Local variable information is only available if the defining class has been compiled with debugging information.  :ABSENT_INFORMATION is one of the conditions that can be signalled by this function.

Function JDI:LINES (method) => list of JDI:LOCATION
Return the list of code locations in this method, ordered by code index.

Function JDI:RETURN-TYPE-NAME (method) => STRING
Return the JNI name of this method's return type.

Local Variables

Represents a local variable in a stack frame.

Function JDI:NAME (local-variable) => STRING
Return the local variable's name.

Function JDI:SIGNATURE (local-variable) => STRING
Return the local variable type's JNI signature.

Function JDI:TYPE-NAME (local-variable) => STRING
Return the local variable type's name.

fixme: hier fehlt noch einiges


Object references are returned by functions like JDI:FIELD-VALUE and JDI:LOCAL-VARIABLE

Note that the referenced object can be garbage collected even though the reference is still alive, unless either virtual machine has been suspended or garbage collection has been disabled explicitly for the object.

Also note that both threads and thread groups are seen as object references by the client, because they are represented by Java instances in the virtual machine.  When sending an object reference, the JDWP server tags the reference with its type, so that the client always knows which type of reference to create.  For example, a reference to an instance of java.lang.Thread will always be of type JDI:THREAD.

Object Methods

Return the object's type.

Function JDI:FIELD-VALUE (field object) => value
Function JDI:FIELD-VALUES (fields object) => list of values
Determine the value or values of the specifed instance fields.

Array Methods

Function JDI:LENGTH (array) => integer
Return the number of array elements.

Function JDI:DATA (array &optional start end) => vector of values
Return the array's elements in a Lisp vector.  With START and END, return only a subsequence.  (START defaults to zero and END defaults to the length of the array.)

Function JDI:ELT (array index) => values
Return element INDEX of the array.


As explained above, JDI:THREAD is a subclass of JDI:OBJECT.

Note that threads have a suspension counter.  A thread needs to be "resumed" using JDI:RESUME as many times as it was suspended before it can run again.  Predicate JDI:SUSPENDEDP determines whether the thread is currently suspended, but there is no way to read the thread's suspension counter directly.  Also note that virtual machine suspension and resumption affects threads in the same way.

Function JDI:FRAMES (thread) => list of JDI:FRAME
Return the thread's current stacktrace.  Note: The thread needs to be suspended for this function to work.

Function JDI:GROUP (thread) => JDI:THREAD-GROUP
Return this thread's group.

Function JDI:NAME (thread) => STRING
Return the thread's name.

Function JDI:STATUS (thread) => SYMBOL
Return the thread's status, one of :ZOMBIE, :RUNNING, :SLEEPING, :MONITOR, :WAIT.  (This function will return NIL for threads with JDWP status -1.  This status value is sometimes reported by Sun's virtual machine, but not documented in the JDWP specification.)

Function JDI:SUSPENDEDP (thread) => BOOLEAN
Determine whether this thread is currently suspended.

Thread Groups

As explained above, JDI:THREAD-GROUP is a subclass of JDI:OBJECT.

Function JDI:CHILD-GROUPS (group) => list of JDI:THREAD-GROUP
Return this groups direct children.

Function JDI:CHILD-THREADS (group) => list of JDI:THREAD
Return the list of member threads (not including the member threads of child groups).

Function JDI:NAME (group) => STRING
Return the group's name.

Return the group's parent, or NIL if this is a top level thread group.

Code Locations

Represents a code location.

Return the type which contains this location.

Class JDI:METHOD (location) => JDI:METHOD
Return the method which contains this location.

Class JDI:CODE-INDEX (location) => INTEGER
Return an implementation-defined integer pointing to this location in its method's executable code.

Stack frames

A stack frame.

Return the stack frame's current location.

Function JDI:THIS-OBJECT (frame) => JDI:OBJECT
Return the current object (this in the Java language).  (Not available in native methods.)

Function JDI:VARIABLE-VALUES (frame locals) => list of values
Return the values of local variables in the frame.  (Local variable information, if available, is returned by JDI:LOCAL-VARIABLES.)


The following example uses a breakpoint request to trace a method.
(defun find-string (name key sequence)
  (find name sequence :test #'string= :key key))

(jdi:with-virtual-machine (vm (jdi:jdwp-connect "localhost" 8000))
  (let* ((class (find-string "Foo" 'jdi:name (jdi:all-classes vm)))
	 (method (find-string "test" 'jdi:name (jdi:methods class)))
	  (make-instance 'jdi:breakpoint-request
	    :suspend-policy :thread-only
	    :location (jdi:location method))))
    (jdi:request-event vm breakpoint-request)
    (jdi:resume vm)
      (let ((set (jdi:read-event-set vm :wait t)))
	(dolist (event (jdi:events set))
	  (describe event))
	(jdi:resume set)))))

To request events, create the appropriate kind of request object (JDI:EVENT-REQUEST) and enable it using JDI:REQUEST-EVENT.  Multiple requests can be made for the same logical event.  For example, a breakpoint on the same location can be set multiple times.  When the event is reported by the virtual machine, an event object (JDI:EVENT) is created for each request.  All such event objects will be reported together as an event set (JDI:EVENT-SET).  To read event sets from the virtual machine's event queue, use function JDI:READ-EVENT-SET.  Event requests specify a suspension policy, one of NIL (don't suspend), T (suspend all threads), and :THREAD (suspend the event thread).  For an event set, suspension policies of the individual requests might not agree with each other.  In that case, the virtual machine will choose a common policy and indicate it in the event set object.  To resume the threads suspended by the event set, invoke JDI:RESUME on the event set object.

Event Requests

Class JDI:WATCHPOINT-REQUEST (jdi:event-request) (jdi:field)

Class JDI:BREAKPOINT-REQUEST (jdi:event-request) (jdi:location)
Class JDI:CLASS-PREPARE-REQUEST (jdi:event-request) ()
Class JDI:CLASS-UNLOAD-REQUEST (jdi:event-request) ()
Class JDI:EXCEPTION-REQUEST (jdi:event-request) (jdi:reference-type jdi:caughtp jdi:uncaughtp)
Class JDI:FIELD-ACCESS-REQUEST (jdi:watchpoint-request) ()
Class JDI:FIELD-MODIFICATION-REQUEST (jdi:watchpoint-request) ()
Class JDI:METHOD-ENTRY-REQUEST (jdi:event-request) ()
Class JDI:METHOD-EXIT-REQUEST (jdi:event-request) ()
Class JDI:STEP-REQUEST (jdi:event-request) (jdi:thread jdi:size jdi:depth)
Class JDI:THREAD-DEATH-REQUEST (jdi:event-request) ()
Class JDI:THREAD-START-REQUEST (jdi:event-request) ()
Use MAKE-INSTANCE to create (but not activate) an event request.

Some request classes have required initialization arguments for certain slots, these are indicated above in the class definitions.  Optionally a suspension policy can be specified with :SUSPEND-POLICY.

Reader JDI:SUSPEND-POLICY (event-request)

Reader JDI:FIELD (watchpoint-request) => JDI:FIELD

Reader JDI:LOCATION (breakpoint-request) => JDI:LOCATION

Reader JDI:REFERENCE-TYPE (exception-request) => JDI:REFERENCE-TYPE
Reader JDI:CAUGHTP (exception-request) => BOOLEAN
Reader JDI:UNCAUGHTP (exception-request) => BOOLEAN

Reader JDI:THREAD (step-request) => JDI:THREAD
Reader JDI:SIZE (step-request) => integer
Reader JDI:DEPTH (step-request) => integer
Readers for user-initialized request slots.

Accessor JDI:PLIST (event-request)
A property list for user-specific data.

Function JDI:REQUEST-EVENT (virtual-machine event-request)
Enable the event request.


Many requests allow optional modifiers, called filters, which further restrict the set of events reported.

fixme: Filter support is present, but not documented. Export the implemented types and implement everything that is missing.

Event Sets

Use JDI:READ-EVENT-SET to read event sets from the virtual machine's event queue.

An unordered collection of events for different requests which were triggered together.

Function JDI:EVENTS (event-set) => list of JDI:EVENT
Return the list of events in this set.

Function JDI:SUSPEND-POLICY (event-set) => a suspension policy
Return the effective supension policy of the event set  The policy is chosen such that the smallest set of events is suspended which satisfies the suspension policies of all event requests involved.

Method JDI:RESUME (event-set)
Resume the threads suspended by this event set (if any).  Equivalent to the appropriate call of JDI:RESUME on the virtual machine or thread mirror in question.

Event Objects

Class JDI:THREAD-EVENT (jdi:event)
Class JDI:LOCATABLE-EVENT (jdi:thread-event)
Class JDI:WATCHPOINT-EVENT (jdi:locatable-event)

Class JDI:BREAKPOINT-EVENT (jdi:locatable-event)
Class JDI:CLASS-PREPARE-EVENT (jdi:thread-event)
Class JDI:CLASS-UNLOAD-EVENT (jdi:event)
Class JDI:EXCEPTION-EVENT (jdi:locatable-event)
Class JDI:FIELD-ACCESS-EVENT (jdi:watchpoint-event)
Class JDI:FIELD-MODIFICATION-EVENT (jdi:watchpoint-event)
Class JDI:METHOD-ENTRY-EVENT (jdi:locatable-event)
Class JDI:METHOD-EXIT-EVENT (jdi:locatable-event)
Class JDI:STEP-EVENT (jdi:locatable-event)
Class JDI:THREAD-DEATH-EVENT (jdi:thread-event)
Class JDI:THREAD-START-EVENT (jdi:thread-event)
Events as returned by the JDI:EVENT-SET methods JDI:EVENTS.

Reader JDI:THREAD (thread-event) => JDI:THREAD
Reader JDI:LOCATION (locatable-event) => JDI:LOCATION
Reader JDI:FIELD (watchpoint-event) => JDI:FIELD
Reader JDI:OBJECT (watchpoint-event) => JDI:OBJECT

Reader JDI:CLASS (class-prepare-event) => JDI:REFERENCE-TYPE
Reader JDI:SIGNATURE (class-unload-event) => STRING
Reader JDI:EXCEPTION (exception-event) => JDI:OBJECT
Reader JDI:CATCH-LOCATION (exception-event) => JDI:LOCATION
Reader JDI:VALUE (field-modification-event) => the field's new value
Readers for event slots.