Chapter 14. Debugging with Eclipse

Table of Contents
Enabling the Debugger Agent
Using the Debugger
Limitations of the Debugging Interface

A debugger is a computer program that is used to test and debug other programs. Debugging is something that programmers cannot avoid. There are many ways to go about debugging, but it essentially comes down to finding the code responsible for an error. In order to fix the error, you need to find the line of code that triggers the behavior. Once the line of code in question has been found, it is also useful to know the context in which the error occurs, and the associated values, variables, and methods. Using a debugger makes finding this information simpler.

The Eclipse Platform features a built-in Java debugger that provides all standard debugging functionality, including the ability to perform step execution, to set breakpoints, to watch for exception that are thrown, to inspect variable values, and to suspend and resume threads. Additionally, you can debug applications that are running on a remote machine. The Eclipse Platform is mainly a Java development environment, but its architecture is open to other programming languages. The Eclipse Platform Workbench and its tools are built around the Java development tools (JDT) components. These components provide the following features to Eclipse:

The Eclipse debugger itself is as a standard plug-in included within the Eclipse binaries. Eclipse also has a special Debug view that allows you to manage the debugging or running of a program in the Workbench. It displays the runtime stacks for the suspended threads for each target you are debugging. Each thread in your program appears as a node in the tree, and the Debug view displays the process for each target you are running. If the thread is suspended, its stack frames are shown as child elements. Figure 14-1 shows the General view of the Debug user interface.

Figure 14-1. General view of the Eclipse Debug View user interface

Enabling the Debugger Agent

The Java Platform Debugger Architecture (JPDA) consists of three interfaces designed for use by debuggers in development environments for desktop systems. The Java Virtual Machine Tools Interface (JVMTI) defines the services a VM must provide for debugging. (The JVMTI is a replacement for the Java Virtual Machine Debug Interface (JVMDI) which has been deprecated.) The Java Debug Wire Protocol (JDWP) defines the format of information and requests transferred between the process being debugged and the debugger front end, which implements the Java Debug Interface (JDI). The Java Debug Interface defines information and requests at the user code level.

A JPDA Transport is a method of communication between a debugger and the virtual machine that is being debugged (hereafter called the target VM). The communication is connection oriented - one side acts as a server, listening for a connection. The other side acts as a client and connects to the server. JPDA allows either the debugger application or the target VM to act as the server. Transport implementations can allow communications between processes running on a single machine, or on different machines. When establishing a connection, a transport address is used to identify the end-point of the connection. The format of a transport address depends on the type of transport.

Within JPDA, the debugger application uses the Java Debug Interface (JDI) and the Connector abstraction to establish a connection to the target VM. The Connector used by the debugger application encapsulates the transport. On the target VM an agent supporting the Java Debug Wire Protocol is used to communicate with the debugger. This agent (which may be built into the target VM or loaded from a runtime library) encapsulates the transport to communicate with the debugger.

A connector is a JDI abstraction that is used in establishing a connection between a debugger application (written to the JDI) and a target VM. Different JDI implementations are free to provide different connector implementations to match the transports and VMs they support. The connector interfaces are very general to allow the JDI to be used with varying connector implementations. Connectors are configured through a set of name/value pairs. Specific connectors accept different name/value pairs.

The following example shows command line options enabling the Debugger Agent when launching the JamaicaVM:

> jamaicavm -agentlib:BuiltInAgent=transport=dt_socket, \
> address=localhost:8000,server=y,suspend=y HelloWorld

The example only listens for a socket connection on port 8000 on the loopback address. It suspends the VM before main class loads. Once the debugger application connects, it can send a JDWP command to resume the VM.

The built in agent accepts a number of additional arguments listed in the table below that can be given with the following syntax:

  -agentlib:BuiltInAgent=<name1>[=<value1>],<name2>[=<value2>]...

Table 14-1. Arguments for built in agent via option agentlib

NameValue
address=[<host>:]<port>Transport address for the connection. If server=n, attempt to attach to debugger application at this address. If server=y, listen for a connection at this address.
server=y/nIf "y", listen for a debugger application to attach; otherwise, attach to the debugger application at the specified address.
suspend=y/nIf "y", suspend this VM before main class loads.