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.