This lab is adapted from a short debugging I found on the web at
http://www.student.math.uwaterloo.ca/~cs-marks/resources/java/jdb/.
Lab6 debugging with jdb
Preparation
- Read through these instructions completely before coming to lab.
- Complete the WebCT "Pre-lab6: debugging" review questions.
- Follow the instructions below and then complete the postlab quiz.
Some initial setup
For this lab you will need to make a copy (in some appropriate
subdirectory of yours) of the two files LetterHome.java and letter1.dat
that are in /afs/cats/courses/cmps012a-cm/lab6.
This is a slightly buggy solution to a programming project from a prior year.
You can find the specification for that problem at
click here.
This program reads its input from a file specified on the command line
(a useful thing to know how to do) instead of
from standard input (the keyboard). This is necessary because the
Java debugging tool, jdb, cannot (easily) be used with programs that read from
standard input. This is because the commands to the debugger are
being read from standard input and the program can't tell which are
debugger commands and which are inputs to your program.
Compiling for the debugger
If you plan to use a debugger (we will use "jdb") with your program, you need
to tell the compiler to include some additional debugging information into the compiled
version. You do this by placing the flag "-g" on the compile line like this:
javac -g MyFile.java
Running the debugger
When debugging programs we generally want to know the values of the various variables
that are computed as the program executes. Sometimes we also want to know which branch of
an if-else is taken or monitor each iteration of a loop.
The java System.out.println statement is and effective way to debug a program.
Placing "debugging printouts" throughout the program at critical places
to monitor the execution can be helpful. These printouts
can easily be commented out when the debugging is completed, and later
uncommented if further bugs show up later.
But what to do when this becomes too tedious? Another option is to
use a debugger, such as jdb. In this lab you will use jdb to
examine the values of some variables in a program and to find an error in
a version of the LetterHome program from programming project 1.
You should start by running the program on the sample input (java LetterHome letter1.dat)
and see that in fact it appears to have (at least) two errors. The expected output is:
Dear Mom and Dad:
Thanks for the stuff you sent.
My classes are going great.
The weather here has been great.
I plan to come home for a visit in a few weeks.
You should get something different. The program has two intentional "errors".
-
To run jdb on our compiled LetterHome program with the input file letter1.dat
type :
jdb LetterHome letter1.dat
-
You will see some output about jdb being initialized, and then you should
see the command prompt "> "
-
If you type help, you will be given a list of the debugger
commands along with a short description of what they do.
-
The first thing to do is set a breakpoint at the very start of the program
so that when it is run, you can step through the application. A
breakpoint is a place in the program where we want it to stop. The
stop in and stop at commands allow you to set breakpoints in the
program. Type in the following to set a break point at the first
line of the main method:
stop in LetterHome.main
-
Now start the program running by typing
run
-
Now the program is being run, and it is temporarily halted. To see
where in the code the program is halted you type
list
It shows you the source code around the next instruction to be executed
(indicated by the =>).
-
Now we want to set a breakpoint after reading in one pair of input integers.
If you type list 30
you will see the code that checks for a valid sentence number.
We can set a breakpont on the line that prints the error message
by typing stop at LetterHome:30.
-
Type cont to continue running to the breakpoint.
-
You can see all of the local variables at this point by typing locals.
- You can let the program advance to the "next" statement by
typing next.
- You can also print out just a single variable such as modifier
with print modifier.
- Do you see the problem with the code here? (Hint: the
spec states that
valid sentence selectors are 1-5 inclusive.)
-
Now we want to debug the problem with the weather modifier. Type list 40. This
lets us see that the method weatherModifier() is called from line 43. Set a break point
there (stop at LetterHome:43), and type cont to continue execution up to the break point.
-
We can now step into the method weatherModifier().
Type step. When you type next the debugger will run
until it reaches the next statement in the current method. If you
type step the debugger will run until it reaches the next
statement that is part of your program even if that statement is the
first statement in a method that is being called.
-
Another variation that you should know about is step up
which runs until you reach the next statement in the method that
called the one you are in (i.e. until the current method returns).
- Can you see the problem? (Hint: when the modifier is 1 the
phrase should be "great".) If not try single stepping
(typing step) a few more times and see if it follows the
expected path.
-
At this point it is worth noting that the up and down
commands allow you to go up and down the call stack to look at the values
of the local variables in the methods that called the current one.
For instance, typing up and locals will
show you the locals in main.
-
Run the program a couple more times and try to play with the other commands.
If you type man jdb from the Unix prompt, you will be presented
with a little more detail about how the commands work.