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 requires a virtual machine that conforms to the specifications of the Java Debug Platform Architecture (JPDA) defined by Sun Microsystems. Starting with version 1.3, the vm shipped with Sun's Java SDK 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.
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 entails the following tasks:
The following sections explain how to perform these tasks.
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-debugger
to
specify JDEBug. To do this,
M-x customize-variable
.
Emacs displays a customization buffer for jde-debugger.
Select any Java source buffer. The JDEBug menu should appear in the Emacs menubar.
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.
To specify the location of the JPDA support libraries for Sun's Java SDK 1.3:
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 . |
To specify the location of the JPDA support libraries for Sun's Java SDK 1.2.2:
Variable | Set to... |
---|---|
jde-bug-vm-includes-jpda-p |
Off. |
jde-bug-jpda-directory |
Directory that contains the JPDA package. |
jdwp.dll
) in your system's library load path.
The libraries live in different places, depending on the platform:
bin
directory. So add the bin
directory to your
system's path environment variable.
For example, suppose the JPDA directory resides in the directory c:/jpda
on your Windows 95 system. In this case, you would include the following line
in your autoexec.bat
file:
set path=c:/jpda/bin;%path%
lib/sparc
subdirectory. So add the lib/sparc
subdirectory to the
LD_LIBRARY_PATH
environment variable of
the Emacs process. The easiest way to do this is to include the setting in
your .bashrc
or .cshrc
file.
For example, suppose you install the JPDA directory at /home/me/jpda
on
your system. Then you would add the following line to your .cshrc
file:
setenv LD_LIBRARY_PATH
/home/me/jpda/lib/sparc:$LD_LIBRARY_PATH
lib/sparc
(Sun processor) or lib/i386
(Intel processor) subdirectory. So for Linux,
you would add lines similar to the following to your .bashrc
file:
LD_LIBRARY_PATH = /opt/jdk1.2.2/lib/i386:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH
Also make sure that there are symbolic links for libjdwp.so and libdt_socket.so as follows:
jdk1.2.2/lib/libjdwp.so
-> jdk1.2.2/lib/i386/libjdwp.so
jdk1.2.2/lib/libdt_socket.so
-> jdk1.2.2/lib/i386/libdt_socket.so
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-sourcepath
. 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:
M-x customize-variable jde-db-source-directories
Emacs displays the customization buffer for the variable.
Note You should specify only the root directories of the top-level packages you
may need to visit during a debugging session. For example, suppose the source files for
your current project reside in a subdirectory of the project directory named
src
and the Java SDK source lives in c:/java/j2sdk1.4.1/src
. Then
the customization buffer should appear as follows:
.emacs
or .prj
file
(see Customizing the JDE).
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
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.
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.
In this guide, a process refers to a running instance of an application. JDEBug provides two commands for launching processes.
This command launches an instance of the application whose
main class is specified by the variable jde-run-application-class
,
or, if this variable is nil
, the application
in the current Java source buffer. The debugger suspends the debuggee process
before it enters the application's main method.
At this point, you should set one or more breakpoints in the
application and select the Run command from the JDEbug menu.
The process will then run to the first breakpoint at which point you can
continue to the next breakpoint or single-step the process.
This command performs the following actions:
Note With this command, the application will simply run to completion without stopping, if you have not previously specified any valid breakpoints for the application or none of the breakpoints exist on the main execution path.
Issuing either of these commands cause JDEBug to split your Emacs frame into two windows and to display a separate local variables frame.
.
The top Emacs 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 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.
The local variables frame displays the application process's local variables. Initially, the frame displays the local variables in the stack frame of the breakpoint hit when you launched the application. If your application does not hit a breakpoint at startup, the local variables buffer displays nothing.
At this point, if the process was launched successfully and did not run to completion, you can begin debugging your application.
See Also
Depending on the version of the JDK you are using, the debugger can launch a debuggee process in either of two modes:
Uses just-in-time (JIT) compilation of classes to speed up execution of a program. This is the mode used in early versions of the JDK. Hence its name.
Speeds up execution by detecting and compiling heavily used fragments of code (hot spots). Unfortunately, the JPDA does not work reliably in this mode (see JDEbug and Hotspot). Therefore, you should use classic mode to launch a debuggee application.
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
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.
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.
To attach via a socket:
-Xdebug
-Xnoagent
-Djava.compiler=NONE
-Xrunjdwp:transport=dt_socket,address=NNNN,server=y,suspend=n
where NNNN
is any unused socket address on the host
processor for the debuggee process.
See jde-run-option-vm-args
for information on how
to specify vm arguments when launching an application from the JDE.
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.
To attach via shared memory:
-Xdebug
-Xnoagent
-Djava.compiler=NONE
-Xrunjdwp:transport=dt_shmem,address=NAME,server=y,suspend=n
where NAME
is a string identifying the process, e.g.,
webserver
.
See jde-run-option-vm-args
for
information on how to specify vm arguments when launching
an application from the JDE.
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.
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.
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.
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.
Note This option is available only if both the debugger and the debuggee process are running under Windows on the same machine.
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.
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.
Use the following vm arguments when launching a process to be debugged in listen mode.
-Xdebug
-Xnoagent
-Djava.compiler=NONE
-Xrunjdwp:transport=dt_socket,address=NNNN,server=n,suspend=y
where TRANSPORT
is either dt_socket
or
dt_shmem
and NNNN
is any symbolic name you want
to use for the shared memory channel or any unused socket address on the host
processor for the debuggee process.
-Xbootclasspath:JDKHOME/jre/lib/rt.jar;JDKHOME/lib/tools.jar
where JDKHOME is the home directory for the JDK.
Note This option is necessary only if you are using the JDK 1.3 vm to launch the debuggee process.
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.
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.
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). This buffer is off by default. |
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. |
JDEbug displays the Process and Locals buffer in windows in the current frame when you launch or attach a process.
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.