JDEbug User's Guide

About JDEbug

JDEbug is a Java debugger that comes with the Java Development Environment for Emacs. It permits you to execute a Java program step-by-step and display and modify the program's internal state. JDEbug features include:

JDEbug Requirements

JDEBug requires a virtual machine that conforms to the specifications of the Java Debug Platform Architecture (JPDA) defined by Sun Microsystems. The vm shipped with Sun's Java SDK 1.3 for Windows and Solaris conform to the JPDA specification.

In addition, JPDA backward compatibility packages are available for Sun's Java SDK 1.2.2 for Windows and Linux platforms, respectively, and for the Reference Version of the SDK 1.2.2 for the Solaris platform.

Note JPDA does not work reliably with the Production Version of the SDK 1.2.2 for Solaris. For example, attempting to attach to a process on the Production Version results in the following error:

Error [4] in accept() call!
err:: Interrupted system call
Socket transport failed to init.
dt_socket transport error; accept failed, rc = -1

If you want to use JDEbug on Solaris, you must use it with the Solaris Reference Version of SDK 1.2.2 or with the Solaris version of SDK 1.3.

The SDK 1.2.2 for Linux includes the JPDA components. You must download the JPDA compatibility packages for the Windows and Solaris versions of SDK 1.2.2 from the JPDA website.

Note The JDE also provides a source-level debugging interface to jdb, the command-line debugger that comes with all version's of Sun's Java SDK. You can use this interface to debug applications running on Sun vm's that do not support the JPDA specification. See Debugging with jdb for more information.

JDEbug and HotSpot

JPDA does not run reliably when a vm is operating in HotSpot mode. For example, JPDA sometimes fails to stop the debuggee process at breakpoints and has trouble getting the this object of the method in which the debuggee process is currently suspended. Sun's JPDA development team is aware of this problem and is working to provide a solution. Meanwhile, you can work around the problem by running the vm in "classic" mode. See Launching an Application in Classic Mode for more information.

Setting Up JDEbug

Setting up JDEbug entails the following tasks:

The following sections explain how to perform these tasks.

Selecting JDEbug As Your Debugger

The JDE is configured by default to serve as a source-level debugger front-end to jdb, the command-line debugger that comes with Sun's Java SDK. To use JDEbug, you must set the value of the JDE customization variable jde-db-debugger to specify JDEBug. To do this,

  1. Type M-x customize-variable.

    Emacs isplays a customization buffer for jde-db-debugger.

  2. Click the radio button next to JDEbug.
  3. Click the State button and select Save for Future Sessions if you want to enable JDEbug for all projects or Set for Current Session if you want to enable JDEbug only for the current project, in which case you should save the setting in your project file.

Select any Java source buffer. The JDEBug menu should appear in the Emacs menubar.

Specifying the Location of the JPDA Libraries

JDEbug uses class and native code libraries that implement the JPDA specification. You must tell JDEbug where these support libraries live. The way to do this depends on the platform and version of the Sun Java SDK you are using.

Sun Java SDK 1.3 for Windows and Solaris

To specify the location of the JPDA support libraries for Sun's Java SDK 1.3:

  1. Select JDEbug->Preferences to display a customization buffer for JDEbug variables.


  2. Customize the entries for the following variables (see Customizing the JDE).
    Variable Set to...
    jde-bug-vm-includes-jpda-p On.
    jde-bug-jdk-directory Directory that contains the Java SDK 1.3. Suppose that the SDK is installed in the directory d:\jdk-1.3 on your system. Then you would set jde-bug-jdk-directory to d:\jdk-1.3.

Java SDK 1.2.2 for Windows, Linux, and Solaris

To specify the location of the JPDA support libraries for Sun's Java SDK 1.2.2:

  1. Select JDEbug->Preferences to display a customization buffer for JDEbug variables.


  2. Customize the entries for the following variables (see Customizing the JDE).
    Variable Set to...
    jde-bug-vm-includes-jpda-p Off.
    jde-bug-jpda-directory Directory that contains the JPDA package.

  3. Include the directory containing the JDPA native code libraries (e.g., jdwp.dll) in your system's library load path. The libraries live in different places, depending on the platform:


Specifying the Location of Source Files

To display the current location in the program you are debugging, JDEBug needs to be able to find the source files from which the program was compile. The JDEbug looks for the files in the source directories specified by the JDE variable jde-db-source-directories. Therefore, before starting a debugging session, you must ensure that this variable specifies all the source files that you may step through during the debugging session.

To set this variable:

  1. Type M-x customize-variable jde-db-source-directories

    Emacs displays the customization buffer for the variable.

  2. Edit the buffer to reflect the location of Java source files on your system.

    Note You should specify only the root directory of the top-level packages you may need to visit during a debugging session. For example, suppose the top-level packages for your current project reside in c:/java/projects/prj1/src and the Java SDK source lives in c:/java/jdk1.3/src. Then the customization buffer should appear as follows:

    jde-db-source-directories: [Hide]
    [INS] [DEL] Path: c:/java/projects/prj1/src
    [INS] [DEL] Path: c:/java/jdk1.3/src/
    [INS]
    [State]: you have edited the value as text, but you have not set the option.
    List of source directory paths. [More]
    Parent groups: [jde-project]

  3. Save the setting in your .emacs or .prj file (see Customizing the JDE).

Starting the Debugger

To start the debugger, select Processes->Start Debugger from the JDEbug menu. This command simply starts the debugger. To debug an application, you must either

Setting the Debug Session Working Directory

The debugger launches all processes from the directory in which it was started. This directory is known as the debug session working directory. By default, the debug session working directory is the directory of the source buffer that was active when you started the debugger. To specify another directory as the working directory for the current debugger session, set the variable jde-run-working-directory to the directory's path.

Note You cannot set the working directory on a per-process basis. All processes launched during the current session start in the debug session working directory.

Exiting the Debugger

To exit the debugger, select Exit Debugger from the JDEbug menu. The JDE terminates any processes (vm's) launched by the debugger and terminates the debugger process (vm) itself.

Note Exiting Emacs itself without first exiting the debugger orphans the debugger vm and any processes (vm's) launched by the debugger. Thus, it is important to exit JDEbug before exiting Emacs.

Launching a Process

In this guide, a process refers to a running instance of an application. JDEBug provides two commands for launching processes.

Issuing either of these commands cause JDEBug to split your Emacs frame into three windows.

.

The top window displays a Java source buffer. The source buffer displays either the source buffer where you launched the application or, if you used the Debug App command, the source buffer containing the first breakpoint hit after the application was launched.

The middle window displays the application process's local variables buffer. The buffer displays the local variables in the stack frame of the initial breakpoint hit when you launched the application. If your application does not hit a breakpoint at startup, the local variables buffer displays nothing.

The bottom window contains the debugger messages buffer for the process that was just launched. This buffer displays messages regarding the status of the process being debugged.

At this point, if the process was launched successfully and did not run to completion, you can begin debugging your application.

See Also

Working with Process Buffers

Debugging Multiple Processes

Launching an Application in Classic Mode

Depending on the version of the JDK you are using, the debugger can launch a debuggee process in either of two modes:

The debugger launches applications in HotSpot mode by default. To launch an application in classic mode, type M-x customize-variable jde-run-classic-mode-vm and toggle the variable on.

Note If the JDK's Java Runtime Environment (JRE) is installed on your system, JPDA sometimes uses the vm installed in the JRE's bin directory to launch the debuggee application. (I'm not sure exactly how the JDPA determines which vm to use to launch a debuggee application. It seems to vary from system to system.) Unfortunately, on Windows, at least, the JDK installer installs only the HotSpot vm in the JRE bin directory. If you want to debug applications, you must manually install the classic mode vm in the JRE bin directory itself. To do this, simply copy the classic subdirectory from the jre subdirectory of the JDK to the bin subdirectory of the JRE. After you have done this, the JRE bin directory should look similar to the following:

    - c:\Program Files\
      - JavaSoft
        - bin
            classic
            hotspot
      + lib

Connecting to External Processes

JDEbug supports two ways of connecting to an application that it does not itself launch: attach mode and listen mode. Each of these modes can be thought of as an interaction between a client and a server. In attach mode, the application vm is the server and JDEbug is the client. In listen mode, JDEbug is the server and the application vm is the client. The advantage of attach mode is that it allows you to connect (and reconnect) to an external process at any time. The advantage of listen mode is that it allows you to debug the startup of an external process.

To use either of these modes, you must start the application vm with certain command line arguments and then issue a JDEbug command to establish the connection. The following sections explain the procedurs for establishing an attach-mode and listen-mode connection, respectively.

Attaching a Process

JDEbug allows you to attach the debugger to an existing local or remote process that was launched outside the current debugger session. This is useful for debugging servlets and processes that were launched by another application, for example, servelets.

NoteYou can use JDE->Run App to launch the third-party application. Use the JDE variables jde-run-executable and jde-run-executable-args to cause the Run App command to run a non-Java app that launches a Java subprocess to be debugged.

You can attach the debugger to an existing process via:

The shared memory option is available only on Windows. It is much faster and thus is preferable. In either case the existing process must have been started with the appropriate debug options.

Attaching via a Socket

To attach via a socket:

  1. Launch the debuggee process with the following vm command line arguments:
  2. Execute JDEbug->Processes->Start Debugger to start the debugger (if necessary).
  3. Execute JDEbug->Processes->Attach Process->Local Host or Remote Host to attach the debugger to a local or remote process, respectively.

    In the first case, the JDE prompts you to enter the socket address that you specified in step 1. In the second case, the JDE also prompts you to enter the name of the host on which the remote process is running.

Attaching via Shared Memory

To attach via shared memory:

  1. Launch the debuggee process with the following vm command line arguments:
  2. Execute JDEbug->Processes->Start Debugger to start the debugger (if necessary).
  3. Execute JDEbug->Processes->Attach Process->Via Shared Memory to attach the debugger to the process started in step 1.

    The JDE prompts you to enter the NAME you specified in step 1.

Note You can attach/detach from a running process as many times as you want during a session.

Listening for a Process

JDEbug's listen mode enables a process that is launched independently of JDEbug to attach itself to JDEbug when the independently launched process starts. Listen mode is useful for debugging the startup code of processes that JDEbug cannot launch itself. Examples of such processes are processes launched by other applications such as a web server or a hybrid C/Java application where a C main program uses an embedded vm to to run Java processes.

NoteYou can use JDE->Run App to launch the third-party application. Use the JDE variables jde-run-executable and jde-run-executable-args to cause the Run App command to run a non-Java app that launches a Java subprocess to be debugged.

When in listen mode, JDEbug acts as a debug server, listening for debug service requests from independently launched processes. You can cause JDEbug to use either a socket or a shared memory channel (Windows only) to communicate with processes requesting debug services. You must use the socket option, if you want to debug a process running on a remote machine or you are running the debugger under Unix, On Windows, you can use either option to debug processes running on the local machine. However, the shared memory option typically results in faster response to debug commands.

Listening on a Socket

  1. Execute JDEbug->Processes->Start Debugger to start the debugger (if necessary).
  2. Select JDEbug->Processes->Listen on->Socket to put JDEbug in listen mode.

    This command causes the debugger to listen on the socket specified by the JDE variable jde-bug-server-socket. The default value is 2112. You can customize this variable to specify any socket address you choose or to cause JDEbug to prompt you to enter an address. Whatever address you choose, you must enter the same address as an argument of the command that launches the process to be debugged.

  3. Launch the debuggee process with the command line arguments required to attach to JDEbug.

    See Listen Mode VM Arguments for more information.

When you launch a Java application with listen mode arguments, the vm halts before running the app's main method and attempts to connect with JDEbug. Once the connection is made, JDEbug is in complete control of the app. For example, the app won't run until the debugger issues a continue command. This means you can set breakpoints in the debuggee app's startup code.

Listening on a Shared Memory Channel

Note This option is available only if both the debugger and the debuggee process are running under Windows on the same machine.

  1. Execute JDEbug->Processes->Start Debugger to start the debugger (if necessary).
  2. Select JDEbug->Processes->Listen on->Shared Memory to put JDEbug in listen mode.

    This command causes the debugger to listen on the shared memory channel specified by the JDE variable jde-bug-server-shmem-name. The default value is jdebug. You can customize this variable to specify any name you choose or to cause JDEbug to prompt you to enter a name. Whatever name you choose, you must enter the same name as an argument of the command that launches the process to be debugged.

  3. Launch the debuggee process with the command line arguments required to attach to JDEbug.

    See Listen Mode VM Arguments for more information.

When you launch a Java application with listen mode arguments, the vm halts before running the app's main method and attempts to connect with JDEbug. Once the connection is made, JDEbug is in complete control of the app. For example, the app won't run until the debugger issues a continue command. This means you can set breakpoints in the debuggee app's startup code.

Listen Mode VM Arguments

Use the following vm arguments when launching a process to be debugged in listen mode.

Here is an example of a typical command line to launch a debuggee client, using JDK1.3:

java -classpath d:/myapp/myapp.jar -Xdebug -Xnoagent
-Xrunjdwp:transport=dt_socket,address=jdebug,server=n,suspend=y
-Xbootclasspath:e:/jdk1.3/jre/lib/rt.jar;e:/jdk1.3/lib/tools.jar
com.myorg.myapp.Main

Use the JDE variable jde-run-option-vm-args to specify vm arguments when launching an application from the JDE.

Debugging Multiple Processes

JDEbug allows you to launch and debug multiple debuggee processes during the same debugger session. JDEbug assigns a numeric identification number to each process that it launches or attaches in either attach or listen mode. All JDEbug commands, except those that launch or attach processes, implicitly address a process called the target process. When you launch or attach a process, that process becomes the target process until you specify a different process as the target process.

To specify a different process as the target process, select JDEbug->Processes->Set Target Process, then enter the ID of the target process at the prompt.

Working with Process Buffers

JDEbug creates a set of buffers for each process that you debug during a debugger session.

Buffer Description
Process Displays status messages from the debugger.
Local Variables Displays the values of local variables and the fields of the object on which the current method was invoked (the implicit this object).
Command Line Interface (CLI) Allows you to interact with a process that has a command line interface (CLI). The JDE sends lines that you type in this buffer to the process's standard input. The process's standard output also appears in this buffer.
Threads Displays the current status of all threads created by the debuggee process. The JDEbug->Display->Threads command creates this buffer.
*JDEbug* Displays the low-level commands sent by Emacs to the Java backend of JDEbug, the backend's responses to those commands, and events detected by the backend. You should always include a copy of this buffer in bug reports as it represents a complete record of your debugs session.

Displaying the Buffers

JDEbug displays the Process and Locals buffer in windows in the current frame when you launch or attach a process.

Deleting Buffers

JDEbug does not delete the buffers belonging to a process when it dies. To delete all the buffers created for dead processes, select JDEbug->Processes->Remove Dead Processes. This command removes all traces of the dead processes from the Emacs environment.