Setting and Clearing Breakpoints via JDWP

A Technical Note for JOS Developers


Introduction

Setting and clearing breakpoints is an inherent requirement of a debugger. Java(tm) debuggers which attach to remote virtual machines are no different in this respect, but how is it actually accomplished? This document identifies the portions of the JDWP specification addressing that question. For JOS developers, a future revision will also supply pointers to the relevant classes in the JOSDI library.

Event Model

The JDWP specification includes a command packet type which is used to inform the target VM about types of events for which a remote debugger is interested in listening. See the EventRequest Set Command for the packet specification and the JDWP.EventKind enumeration for a list of supported event types.

The VM also needs to know whether any threads should be suspended when an event occurs. That information is described via a field in the command packet which selects the desired suspend policy.

The VM notifies the remote debugger when selected events have occurred via the Event Composite Command. This is a reversal of roles in which the VM initiates communication with the debugger, rather than the opposite which is normally the case. It also underscores the fact that the JDWP is an asychronous protocol -- understandble, since the debugger cannot predict when breakpoints will be hit. Both the debugger implementor and the VM implementor must anticipate this.

Breakpoint and Single-Step Events

So, the debugger gets to hear about lots of different things that happen during its interaction with the VM. Among those different things are breakpoints and single-steps. In this context, when I write breakpoints I'm actually lumping several event types together:

Note that the location of a user-defined breakpoint can be as specific as the offset of a VM instruction in the bytecode implementing a method.

From the debugger's perspective, this subset of event types, in combination with the previously-mentioned thread suspension policies, is the mechanism by which breakpoint behavior is achieved. The VM, on the other hand, is free to choose any appropriate implementation strategy which preserves the abstraction. In the most likely scenario, the VM takes an event request as a cue to physically enable the event (e.g., set the breakpoint). But, the JDWP doesn't require that to be the case.

Single-stepping behavior is accomplished using the same command packet and thread suspension policy.

The EventRequest Clear Command indicates that the VM should no longer notify the debugger about the specified event. The acts of unsubscribing from an event type and actually disabling the cause of the event are decoupled.

In addition, there is a command packet for clearing all breakpoints. See the EventRequest ClearAllBreakpoints Command.

Wrap Up

In my opinion, this is an extremely flexible architecture. One key aspect is the abstraction of subscribing to event types, which decouples semantics on the debugger side from implementation details on the virtual machine side.

Also, a variety of breakpoint behaviors can be achieved through judicious choice of event types and thread suspension policies.

Finally, the fact that run-time behavior of application code is inherently unpredictable underscores the need for debuggers and virtual machines to handle asynchronous operation, particularly where breakpoints are concerned.


Copyright © 2001 by Jack D. Unrue
All rights reserved.

Last updated: 9 March 2001