This is the mail archive of the
mailing list for the Java project.
Overview of interpreted debugging design
- From: Keith Seitz <keiths at redhat dot com>
- To: GCJ Mailing List <java at gcc dot gnu dot org>
- Date: Thu, 26 May 2005 12:22:22 -0700
- Subject: Overview of interpreted debugging design
As I mentioned with the âannouncementâ, I've composed a little (10,000
foot/meter) overview of the design of the back-end. While I always
strive to document the code thoroughly, a little run-down of the
situation couldn't hurt. I firmly believe that the code largely speaks
Many of you are probably [painfully] aware of Sun's Java Platform
Debugger Architecture, which outlines several complete components for
Java debugging. One of these components is the Java Debug Wire Protocol
(JDWP) which describes the format of communications between a debugger
and a virtual machine. Some of the other components of the JPDA (like
JDI) may be built on a JDWP back-end.
There are several goals that I had in mind when I began working on
adding a JDWP back-end to gcj. While I attempted to keep these goals in
mind while designing and coding, I may have lost my way and neglected
one goal or another. I believe that in such cases, I have not so
neglected the design that the neglect could not be easily rectified.
With that disclaimer, let me make clear: It is paramount that any design
and implementation must impact non-debugging sessions as minimally as
possible. All the other goals be damned, this is always foremost in my
mind. [Right now, there is only one intrusive place where debugging
could interfere with the non-debugging session: event notification.
Currently, all that is required of the VM is a check on a global
variable in the non-debugging case. I don't think there is a way to have
any less an impact, but if someone has any ideas, I would love to hear
Another important goal (one which may substantiate my disclaimer about
neglect) is VM-neutrality. The back-end is intended to be re-used by any
virtual machine. This makes the back-end a prime candidate for inclusion
in GNU Classpath. Since I (and Red Hat) am (are) only immediately
interested in gcj, the package layout is very gcj-centric. A simple
refactoring would easily âfixâ this.
Alas, the last nebulous goal is to have a JDWP back-end which is fast. I
have no doubt that Brooks's âprepare to throw one outâ axiom will apply
to this round of design and implementation.
Having said all that, let me now dive into some specifics, starting with
overall functional design and package layout.
The back-end is segregated into several packages which deal with the
most important areas of functionality:
The topmost package for all things related to JDWP. The Jdwp class is
called to initialize the back-end and virtual machines use this class as
the main interface to the back-end. This package also contains the
virtual machine interface that other virtual machines may use to add
This package deals with event notifications and requests. It contains
classes used by the virtual machine to create event notifications and
classes used by the JDWP back-end implementations to create and manage
event requests from the debugger.
This package contains classes which deal with object management. All
objects in the virtual machine are reported to the debugger using ID
âpointersâ. It manages both transient objects and object types.
This package deals with processing commands from the debugger. It uses
the virtual machine interface defined by gnu.gcj.jdwp to do virtual
machine-specific tasks, such as inserting breakpoints, retrieving class
This package contains classes which concern the actual transport layer
used between the debugger and the JDWP back-end, including packet queues
and startup negotiation. The JDWP protocol allows for a number of
transport layers such as sockets and shared memory. The actual transport
layer in use is specified at runtime with the â-Xrunjdwpâ option. Right
now I have only implemented a socket transport.
Now for some more nitty-gritty details: the threading model. The JDWP
back-end consists of three threads: a transport thread responsible for
reading packets off the transport, a packet processing thread (may
choose to use multiple threads), and the âmainâ thread which eventually
runs the user's application.
Aside from these threads, the virtual machine has its own sets of
threads which include the garbage collector and bytecode interpreter
threads (amongst others). The only non-back-end threads that execute
back-end code are the interpreter threads during event notification.
When an event occurs in the virtual machine, the executing thread must
first check if the virtual machine is debugging. If debugging is
enabled, the thread creates an event, and passes it to the back-end for
notification. The same thread then searches a list of event requests
from the debugger. If none is found, the thread returns to executing
If an event request is found, the thread then packages the event into a
packet and sends the request to the debugger. The interpreter thread
will execute all the steps necessary to construct the event notification
as a JDWP packet and pass it to the kernel for transport to the
debugger. There is no send queue, although it could be added easily
enough at a later date should it prove necessary.
After the event notification has been sent to the debugger, the thread
follows the suspend policy requested by the debugger (suspend no
threads, this thread, or all threads). If any threads are to be
suspended, the thread calls on virtual machine interface to do the
So, unless people want more specific information on anything, I am ready
to start the review process. I would think the easiest place to start
would be the transport layer (gnu.gcj.jdwp.transport), but I am willing
to start wherever people would like.