Today's lab is a blast from the past on debugging; we include it
because it gives an introduction to jdb
, the debugger
that comes with the JDK. jdb
can provide a more
convenient method of debugging programs than the manual approach
involving generous sprinkling of System.out.println
calls
throughout your code.
The first section covers the manual sort of debugging you already know about, but also the additional idea of having a special debugging log class that allows you to turn debugging output on and off in your programs without having to change the source code all over the place.
The second section covers some of the basics of using
jdb
, the Java source-level debugger. jdb
is
reputed to be more stable in JDK 1.2 than in previous versions, but if
you try it out on the upcoming assignments and find that you have
problems using it, you can always fall back on the debug class idea.
Ideally, programs are written correctly the first time and therefore never require debugging. Almost as ideal is to catch the errors in the program simply by thoroughly examining it, usually running it on various test cases in your mind and/or verifying invariants about what should be and must be true at this point. Evaluating the correctness of a program by examining the code is known as inspection.
Unfortunately, most of us have difficulty writing a correct program from scratch, or even removing our errors by inspection. This is particularly difficult in larger programs, or even virtually impossible unless programs are written with careful attention to modularity and abstraction. Therefore, programmers learn a variety of debugging techniques that involve actually executing the code on a computer.
Although inserting print statements is a simple technique that can be used on virtually any system, it has the major disadvantage that the programmer has to specify what to display before executing the program. If one realizes that key information is not displayed, the program usually has to be edited to add additional print statements and then recompiled and restarted. A "shotgun" approach that displays any potentially relevant data may be employed instead, but significant time will be required to make sense of the large quantity of output.
While debugging using print statements is usually not the best technique for finding bugs, it may be useful in a context with limited interactivity or language support. Systems currently in use often support logging status data to a file, so as to provide at least some information about what went wrong if a problem occurs. Likewise, if software support for more sophisticated approaches such as interactive debuggers is not available, logging status output to a console or file may be useful.
If debugging using print statements is done, many programmers like to be able to control the output without having to modify each print statement. Here's a simple way to do that in Java:
class Debug { public static boolean on = true; public static void print( String s ) { if (on) System.out.println(s); } }Use Debug.print() inside this file much as you would have used println():
Debug.print("We're here!");Allowing your Debug class allow logging to a file is straightforward.
Good development environments provide a tool known as an interactive debugger, or more simply, a debugger. Debuggers allow examination of the status of a program that is currently executing. This provides one with a "window" into the operation of a program, through which control flow and variable values are visible whenever sought.
The Java tools we're the using, known collectively as the Java Development Kit, include a debugger called jdb. It allows us to do many useful things, such as examine variable values, see which methods are currently executing and who invoked them, and set breakpoints to make the program stop at various points.
Be warned that jdb is sometimes buggy. However, the same concepts covered here will apply to using other debuggers as well.
In our example, the initial debugger prompt is:
Later it becomes:
Why does it change, and what do main and 1 signify? (Hint: what else could be listed there? Think about the fact that you'll probably never see them change to any other values (at least in any Java program we'll write in Comp212).)