Debugging Using JDB
While testing your program, you may
encounter errors ("bugs") in one of two ways: - the program
may crash (throw an exception), or
- it may produce incorrect
output.
In either case, you can use the debugger jdb
to help track down the error.
To learn about using jdb, print and read the JDB
Quick Reference Guide. Then try the two exercises below.
Example 1: Using jdb after a crash
- Create a new
directory and copy into it the following three
files:
- Person.java
- Bug.java
- Makefile
The file Person.java
defines a very simple Person class, with a constructor that
initializes the person to be 10 years old, and an age method
that returns the person's current age.
The program in Bug.java
includes the declaration of a Person array.
It uses a loop to verify that everyone in the array has been
initialized to be 10 years old.
The Makefile can be used to make Bug.class
(see step 2 below).
- Create Bug.class (type: make Bug.class).
- Run the Bug program (type:
java Bug).
This should cause a null pointer exception to be thrown.
If the error message does not tell you where the
exception occurred, run the program again as follows:
java -Djava.compiler=NONE Bug
This time you should see that the exception is thrown on line 10.
- Use jdb to find the problem. First type:
jdb Bug. When jdb is ready (it gives you a
">" prompt), tell it to stop at the beginning of the program
by typing: stop in Bug.main, then start the program
by typing: run Bug
- You should get a message saying that your breakpoint was hit.
- Now you can set another breakpoint at the statement that caused
the null pointer exception by typing: stop at Bug:10
(Note that when you set a breakpoint at a method, you must use
stop in
and a dot, while when you set a breakpoint at a line number you
must use stop at and a colon.)
Now let the program continue running until it gets to line 10, by
typing: cont
- The program will stop the first time it gets to line 10.
Type list to see line 10 and the surrounding lines.
You should see that line 10 is:
if (family[j].age() != 10) {.
A null pointer exception means that there was an attempt to
access a field or method of an Object whose value is null.
On line 10, the age method of family[j]
is being called. Is it possible that family[j] is null?
To see whether this is indeed the case, type:
print j (jdb should print j = 0), then type
print family[0].
You should find that indeed family[0] is null, so
it is wrong to try to call its age method.
- Look at the previous code that set the value of family.
Do you understand why family[0] (and all of the other
elements of the array) are null?
Example 2: Using jdb to understand bad output
- Exit from jdb by typing: quit.
Fix the problem you discovered in Example 1 by editing
Bug.java.
- Make a new version of Bug.class (type:
make Bug.class).
- Run Bug again.
It should not crash, but you should get lots of messages saying
that the people in the array are not 10 years old.
It seems that either the Person constructor method or its age method
is not working.
We can find out whether the Person constructor is working by
printing the value of a Person's myAge field after the
constructor has been called.
- Run jdb again (type: jdb Bug), and set a breakpoint
at the beginning of the program (stop in Bug.main).
Then start the program (run Bug).
- Use the list command to look at the code to see where
to set the next breakpoint.
Find the line number where you call the Person constructor, and
set a breakpoint there, then continue execution.
- Use the next command to execute the current line (the
call to the Person constructor).
- Use the print command to look at the value of
the Person's "myAge" field (print family[0].myAge).
- You should see that the value is 0, instead of 10 as expected.
- Look at the code for the Person constructor (unfortunately,
there doesn't seem to be a way to do this in jdb unless you
are currently stopped at a breakpoint that is in a Person method,
so you'll have to use a text editor in another window to look at
the code).
Can you find and fix the problem?