Return to index

Tracing and Debugging

 

Introduction

Debugging is the process of finding, and then fixing, run-time errors. You can only debug code which compiles!

A 'bug' is when a program does something it should not - or doesn't do something it should! A bug may or may not generate an exception.

When you notice a bug, examine the actual behavior and try to think out what is going on. Look at it several times. You can examine your code in suspected places and perhaps draw some diagrams on paper to be clear about the logic employed. Adding some System.out.println()s can also be helpful - both to check values and that a method or method part is actually performed, and when.

Then there is tracing and the debugging tool to help out. The debugging tool lets you run the program until a specified 'breakpoint' is reached whereupon you can step through the code line by line, examining values as you proceed.

 

Tracing and Profiling

Tracing is an excellent way to debug your programs, for verifying how your program behaves, and for determining how much time is spent in each method. Tracing is available for both applets and GUI based applications (Swing or AWT).

With TJI, using tracing is very straightforward. Simply choose to run your program with tracing, and TJI will log the entry and exit of every constructor and method of the project. It also shows how much time was spent in each method. Further, TJI logs the value of every variable (both objects and primitives, and all scopes) whenever created or assigned; the same applies for object fields.

If you run with tracing in 'quiet mode', the tracing log is not shown until after the program has terminated. This allows the program to run at very nearly full speed, so 'quiet mode' is the best choice when time profiling is the primary aim.

If the program terminates as the result of an uncaught exception, the exception details are appended to the trace log - and the run-time error location is indicated in the source files as usual.

The profile results table, which is sortable, is shown automatically after your program stops running. You then have the choice of looking at the trace log. There are hyperlinks from the trace log to the source code.

Note that the timings given by the tracing tool will be more accurate when tracing is run in 'quiet mode' (view later). However, tracing will still affect the timings a little bit - an approximate average is that the timings will be 10% greater than without tracing but this could vary from near 0% to 20%. In any case, timings would depend on the target machine, how many other processes are active, etc. Nevertheless, tracing timings provide a guide to where, in relative terms at least, your program spends its time. This can be invaluable for determining where to concentrate effort when trying to make your software more efficient and faster running.

 

Using the Integrated Debugging Tool

This is based on JDB. You will still need to have an idea of where in your code things go wrong (though often the critical error occurs earlier, you can discover it this way). You will then specify a particular code line to be a breakpoint. You can have multiple breakpoints if you wish. Note that a break point should be a line of code - not a method header.

At a breakpoint, the program is suspended (well, actually only the thread running that line) just before that line is executed. With the thread suspended, you can examine object or primitive (int, long etc) values while stepping onwards through your code using step, next or method (the differences are detailed below). To resume the program (until another or the same breakpoint is met, use continue. Similarly, references to a current line of code in the debugging windows are to the line that will be executed next.

TJI provides a graphical interface for the jdb tool within the JDK. Besides providing a set of buttons for the most useful commands, it also allows you to set breakpoints in the editors before a debugging session is started. To set or unset a breakpoint, use the right-hand mouse button to click on a line number to the left of the source code. When set as a breakpoint, the line number will appear with a yellow background. Set breakpoints only on source lines with actual code, not method headers or lines with only a brace.

Note that the debug tool is not currently available for applets. However, it is possible to write an applet in such a way that it can also be run as an application - and in this way you can debug your applets.

Java programs are usually 'event-driven' (certainly if they have a user interface). When the program is waiting for an event (a button press, for example), none of your code is currently being executed and so at these times pressing 'locals' or 'step' etc. will show the response 'no thread is currently suspended'. Indeed, only when the normal flow of execution is suspended is it possible for the debugging tool to show a code position, object and primitive values, or a stack trace.

Note that to see your breakpoints in the editors, color syntax formatting must be enabled (see the 'Options' menu).

Also, note that when a breakpoint is reached, the application being debugged will effectively 'freeze' (be suspended). You may choose to move the IDE frame to the right a bit so that can see and easily jump to and from your application frame.

When you select 'Debug', TJI's standard tool bar is replaced by a debugging toolbar with all the functions you may use during the debugging process. When the program exits, or you select the 'Exit' function from the debugging tool bar, the standard tool bar is restored.

When an exception occurs for which there isn't a catch statement anywhere in the throwing thread's call stack, the VM normally prints an exception trace and exits. When running under jdb, however, control returns to jdb at the offending throw. TJI will then indicate the exception location and details.

Here is a description of the available commands :

Step ('run next line')

The 'step' command advances execution to the next line of source code - the one shown in the JDB output and current editor position. This step can be termed 'step over' and is distinct from 'step into' which would step through all called methods source code too. If there are called methods you are also interested to step through, remember that you can set any number of breakpoints in different source files.

Run to the end of the current method

The 'method' command advances execution to the end of the current method in the current stack frame.

Continue (run)

Continues execution of the suspended application after a breakpoint, exception, run to end of current method or step. The application will continue to run normally until another (or the same) breakpoint is reached or an uncaught exception is thrown.

Locals

Shows the basic details of the local variables, objects and primitives (those whose scope is the current method).

Show object details

Shows the basic details of the object, object field or primitive entered into the corresponding text field. You can also enter Java expressions. Suppose we want to know the size of a Vector instance called 'v'. We can type the expression v.size() into the textfield and then click the 'Object' button to see the size value in the debugging output window. Most standard Java expressions can be used; for example, v.elementAt(0). You can even enter 2+3

Monitor object

To keep an eye on a value as you step through your code you can enter the object, object field or expression in the associated textfield.

JDB command

You can type any other JDB command into the associated textfield and press this button to enter it. One use ful command is 'watch [object/object field/expression]' which you can enter once stopped at a breakpoint. This will output the value at any time that the value changes (whereas Monitor will show the value at every step).

Method call stack

Shows the stack of method calls that led to the current method. You can only request this when there is a current method - that is, the application being debugged is currently suspended as it is when a breakpoint is reached or when stepping through your code.

 

Return to index