Data Structures, Algorithms, & Applications in Java
The Java Debugger JDB
Copyright 1999 Sartaj Sahni

Introduction
Some JDB Commands
An Example

Introduction
Computer assisted program tracing is a common approach to debugging a program. In this approach, we execute portions of the code and examine the values of certain variables. A rather painful way to trace through your program is to manually introduce a whole bunch of statements that will print the values of variables you want to monitor, run the modified program, study the output, fix the detected bugs, rerun the program, detect new bugs, introduce more print statements, and so on. When you are satisifed that your program runs properly, the debugging statements you introduced are removed and the program rerun to ensure that you did not remove statements that were not to be removed.

The task of debugging is greatly simplified when you use a debugger such as jdb which comes with the Java Development Kit (JDK). This debugger lets you step through your program, printing the values of any variables you may be interested in, without making any change to the source code. Some of the jdb commands you will find useful when debugging programs in this book are described below.

Some jdb Commands
Here are some useful degugging commands. For a complete list of commands, consult your Java documentation.


catch
list the exceptions that are being caught

catch ExceptionClassName
suspend execution whenever an exception of type ExceptionClassName is thrown; treats exceptions of this type as breakpoints

clear
list all breakpoints and their line numbers

clear TheClassName:theLine
remove the breakpoint at line theLine of the class TheClassName

cont
continue execution from current breakpoint; suspend when next breakpoint is reached or when program terminates

exit
terminate the jdb session

help
list all jdb commands

ignore ExceptionClassName
do not suspend execution when an exception of type ExceptionClassName is thrown; opposite of catch

list
list from 4 lines before the current source code line to 4 lines after

list theLineNumber
list the source code beginning at line number theLineNumber - 4 to theLineNumber + 4

locals
list the value of each local variable

methods theClassName
list all methods of the class theClassName

print theObject1 theObject2 ...
print the value of each of the objects theObject1, theObject2, ...

quit
terminate the jdb session; same as exit

run
begin execution of the main method of the class specified in the jdb command line; suspend when a breakpoint is reached

step
execute the current line of the source code and suspend execution

stop
list all breakpoints; same as clear

stop at TheClassName:theLineNumber
set a breakpoint at line theLineNumber of the class TheClassName

stop in TheClassName.theMethodName
set a breakpoint at the first executable line of TheClassName.theMethodName

where
list invocation sequence used to get to current line


An Example
We illustrate the basic capabilities of jdb using Program 1.28 (output the roots of a quadratic equation) as an example. Suppose that the first line of QuadraticRoots.main is

outputRoots(1, -5, 6);

To use the full capability of jdb, you should compile your program using the -g (include all debugging information) option, as shown below.

javac -g applications\QuadraticRoots.java

A sample jdb debug session is shown below. The line numbers 1-40 shown in the first two columns of each line have been added by us; these numbers are not part of the display you will see during a jdb session. In the shown session c:\codes is a DOS prompt; and > and main[1] are jdb prompts. Line 1 invokes the debugger; lines 2 and 3 are responses from jdb; in line 4, we ask that a breakpoint (i.e., a point where the execution of our program is to be suspended) be set at the first line of the method outputRoots; line 5 is a response from jdb. In line 6, we instruct jdb to run our program; execution begins at the method QuadraticRoots.main and stops when the first breakpoint is reached. The run command also causes the jdb prompt to change to main[1], which signifies that our program is the active thread. In line 10, we have used B hit as an abbreviation for Breakpoint hit so that the line width would not exceed the width of this page. In your actual session, you will see the full expansion Breakpoint hit. QuadraticRoots:18 tells us the breakpoint hit is in line 18 of the class QuadraticRoots. This must be the line number for the breakpoint we set in session line 4. In line 11, we ask that the values of the variables a, b, and c, which are the formal parameters of outputRoots, be printed; lines 12-14 shows their values as printed by jdb. In line 15, we ask that source code lines around line 20 be listed. This results in lines 16-24 being listed (jdb lists from 4 lines before to 4 lines after the requested line). Quite by coincidence, the line numbers of our session match the source code line numbers that are output. By examining the output, we see that the first executable line of outputRoots is numbered 18. Therefore, our stop request of session line 4 sets a breakpoint at line 18 of the source code.

 1  c:\codes>jdb applications.QuadraticRoots
 2  Initializing jdb ...
 3  0xae: class(applications.QuadraticRoots)
 4  > stop in QuadraticRoots.outputRoots
 5  Breakpoint set in applications.QuadraticRoots.outputRoots
 6  > run
 7  run applications.QuadraticRoots
 8  running ...
 9  main[1]
10  B hit: applications.QuadraticRoots.outputRoots(QuadraticRoots:18)
11  main[1] print a b c
12     a = 1.0
13     b = -5.0
14     c = 6.0
15  main [1] list 20
16  16             public static void outputRoots(double a, double b,
                                                            double c)
17  17             {
18  18                if (a == 0.0)
19  19                   throw new IllegalArgumentException
20  20    =>                ("QuadraticRoots: Coefficient of x^2 must
                                                        be nonzero");
21  21
22  22                double d = b * b - 4 * a * c;
23  23                if (d > 0) {// two real roots
24  24                            double sqrtd = Math.sqrt(d);
25  main[1] stop at QuadraticRoots:23
26  Breakpoint set at applications.QuadraticRoots:23
27  main[1] stop at QuadraticRoots:25
28  Breakpoint set at applications.QuadraticRoots:25
29  main[1] cont
30  B hit: applications.QuadraticRoots.outputRoots(QuadraticRoots:23)
31  main[1] locals
32     a = 1.0    // 2 output lines omitted
33     b = -5.0
34     c = 6.0
35     d = 1.0
36  main[1] cont
37  B hit: applications.QuadraticRoots.outputRoots(QuadraticRoots:25)
38  main[1] print sqrtd
39  sqrtd = 1.0
40  main[1] quit


Knowing what source code lines 22 and 24 are, we decide to set breakpoints at source code lines 23 and 25 (see session lines 25 and 27). Line 29 instructs jdb to continue the execution of the program. Execution continues until the next break point is encountered. In our case, execution stops just before the execution of line 23. Line 31 asks that the values of local variables (that are in scope at this point) be printed, and line 36 instructs jdb to continue execution until the next breakpoint. The next breakpoint is encountered at line 25 of the source code. So, execution stops just after source code line 24 is complete, but before source code line 25 is started. Line 38 asks that the value of the variable sqrtd be printed, and line 40 terminates the jdb session.