Controlling program execution
The most important characteristic of a debugger is that it lets you control the execution of your program. For example, you can control whether your program executes a single line of code, an entire method, or an entire program block. By manually controlling when the program should run and when it should pause, you can quickly move over the sections that you know work correctly and concentrate on the sections that are causing problems. The Debugger lets you control the execution of your program in the following ways:
The execution point
When you're in a debugging session, the line of code that is the current execution point for a thread is highlighted in the Source pane. A green arrow
is displayed in the left margin.
The execution point marks the next line of source code to be executed by the Debugger. Each thread has its own execution point. Whenever you pause the program execution within the Debugger, the current execution point for the selected thread is highlighted. The execution point always shows the next line of code to be executed, whether you are going to trace, step, or run your program without stopping.
To see where the current execution point is for a thread,
- Select a thread in the Threads and Stack pane.
- Choose Run|Show Execution Point.
The Debugger displays the block of code containing the execution point.
If no source code is available when you choose Run|Show Execution Point, a "No source available" message is displayed. If the execution point is in a class that has Trace Into set to Disabled, Show Execution Point has no effect.
Finding the execution point
While debugging, you're free to open, close, and navigate through any file in the Source pane. Because of this, it's easy to lose track of the next program statement to execute, or the location of the current program scope. To quickly return to the execution point, choose Run|Show Execution Point.
If there is no source associated with the code at the current execution point, a "No source available" message appears.
Moving through code
The Run|Trace Into and Run|Step Over commands offer the simplest way of moving through your program code. While the two commands are very similar, they each offer a different way to control code execution.
The smallest increment by which you step through a program is a single line of code. Multiple program statements on one line of text are treated as a single line of code; you cannot individually debug multiple statements contained on a single line of text. The easiest approach is to put each statement on its own line. A single statement that is spread over several lines of text is treated as a single line of code.
Tracing into a method call
The Run|Trace Into command executes a single program statement at a time. If the execution point is located on a call to a method, the Trace Into command steps into that method and places the execution point on the method's first statement.
If the execution point is located on the last statement of a method, choosing Trace Into causes the Debugger to return from the method, placing the execution point on the line of code that follows the call to the method you are returning from.
The term single stepping refers to using Trace Into to successively run though the statements in your program code.
There are several ways to issue the Trace Into command:
- Select Run|Trace Into.
- Press F7 (default key mapping).
- On the toolbar, click the Trace Into icon
.
Stepping over a method call
The Run|Step Over command, like Run|Trace Into, enables you to execute program statements one at a time. However, if you issue the Step Over command when the execution point is located on a method call, the Debugger runs that method without stopping (instead of tracing into it), then positions the execution point on the statement that follows the method call.
There are several ways to issue the Step Over command:
- Select Run|Step Over.
- Press F8 (default key mapping).
- On the toolbar, click the Step Over icon
.
As you debug, you can trace into some methods and step over others. If you are confident that a method is working properly, you can step over calls to that method, knowing that the method call will not cause an error. If you aren't sure that a method is well-behaved, trace into the method and check whether it is working properly.
Running and pausing your program
You can pause your program when the program is running in the Debugger. Pausing causes the Debugger to pause your program the next time the execution point enters code for which the source is available. You can then use the Debugger to examine the state of your program with respect to this program location. When you have finished examining that part of the program, you can set another pause condition and then continue running the program to that point.
To pause your program, do one of the following:
- Select Run|Program Pause.
- On the toolbar, click the Pause icon
.
When you are using the Debugger, your program can be in one of two possible states: "running" or "paused."
- When your program is waiting for user input, it is still considered to be "running." When your program is in the "running" mode, the Pause button is available and the word "Running" appears in the Status Bar.
- When your program is "paused," the Run, Step Over, and Trace Into buttons are available.
If you click Pause while the Debugger is processing classes for which Trace Into is set to Disabled, the Pause button has no effect, and no execution point is shown. None of the source code in the classes for which tracing is disabled can be shown, and the Debugger continues processing until it finds a piece of code that it can trace into.
Typically when debugging, you step over a line that represents many different classes, all of which you have set Trace Into to Disabled. While the Debugger is running the classes for which Trace Into is set to Disabled, the Debugger is in "running" mode.
Running to a breakpoint
Set breakpoints on lines of source code where you want the program execution to pause during a run. Running to a breakpoint is similar to running to a cursor position, in that the program runs without stopping until it reaches a certain source code location. Unlike the running to the cursor position, however, you can have multiple breakpoints in your code. You can customize each breakpoint so it pauses the program execution only when certain conditions occur.
For more information about breakpoints, see the Using breakpoints topic in this chapter.
Running to the end of a method
The Run|Run To End Of Method command runs your application at full speed until it reaches the end of the current method.
This command is disabled in two situations: when you reach the end of the method, or with code that's been compiled with a non-Borland compiler.
Running to the cursor location
You can run your program to a spot just before the suspected location of the problem. At that point, check that all data values are correct. Then run your program to another location, and check the values there.
To run to a specific program location,
- In the Source pane, position the cursor on the line of code where you want to begin (or resume) debugging.
- Choose Run|Run to Cursor or right-click and choose Run to Cursor.
When you run to the cursor, your program executes without stopping until the execution reaches the location marked by the text cursor in the Source pane. When the execution encounters the code marked by the cursor, the Debugger regains control, pauses your program, and places the execution point on that line of code.
Restarting the program
During debugging, you may need to restart the program from the beginning. For example, you might need to restart the program if you step past the location of a bug, or if variables or data structures become corrupted with unwanted values. To end the current program run and reset the program, choose Run|Program Reset.
Resetting a program closes all open program files, releases resources, and clears all variable settings. However, resetting a program does not delete any breakpoints or watches that you have set, which makes it easy to resume a debugging session.
Viewing method calls
The Threads and Stack pane shows the sequence of method calls that brought your program to its current state. The call stack also shows the arguments passed to a method call - each method listed in the pane is followed by a listing that details the parameters with which the call was made.
To view the source code located at a particular method call, right-click a method in the Threads and Stack pane, and select Goto Method.
The Threads and Stack pane shows where each method resides. This pane lists the thread name, what line the method call is on, what the package is, and the file name.
Showing where a method was called
The call stack is particularly useful if you accidentally Trace Into code that you wanted to Step Over.
To step back and then resume stepping where you originally intended:
- Double-click the call that called the method you stepped into by mistake. It will be the second call from the top in the call stack.
The Source pane becomes active with your cursor positioned at the location of the call.
- Move the cursor in the Source pane to a position completely past the call.
- Set a breakpoint.
- Select Run|Run to run to that breakpoint.
Viewing the Execution Log
The Execution Log window shows a record of events that have occurred so far during the current debugging session. The following is an example of the Execution Log:
To open the Execution Log, choose View|Execution Log.
To control which types of information are included in the Execution Log:
- Right-click in the Execution Log window, and select Properties.
The Log Properties dialog box appears.
- Check the check boxes for the types of data to record in the log, and click OK.
To type in your own text and save the log to a file, right-click, and select Save To File.
Enabling and disabling tracing into classes
To closely examine part of your program, disable Trace Into for all files used in your project, then enable tracing on only the files you want to step through in the Debugger. This way, you can concentrate on a known problem area, rather than manually stepping every line of code in the entire program. For example, you usually don't want to step through classes that are in the Sun library, because you're not going to do troubleshooting on them; you usually only want to inspect and troubleshoot your own classes.
To set the Trace Into settings, select the View|Loaded Classes command. The Loaded Classes window appears, showing all the classes that have been loaded so far during this debugging session.
Icons for the Loaded Classes window
|
Icon |
Description |
 |
Class with Tracing Into enabled |
 |
Class with Tracing Into disabled |
 |
Package with Tracing Into enabled |
 |
Package with Tracing Into disabled |
|
If you make any changes to the tree in the Loaded Classes window, the Tracing Disabled list, displayed in the List of Packages And Classes With Tracing Disabled window, will be automatically updated, and vice versa.
To enable Trace Into for a class that has been loaded:
- Select View|Loaded Classes.
The Loaded Classes window appears.
- Expand the package so you can see a path from the top level of the package down to your class.
- Right-click the top-level package containing your class, and select Disable Tracing (Trickle).
The top-level node and all nodes under it are marked as Disabled.
- Start from the top-level node and work your way down to the class; at every node along the way, right-click and select Enable Tracing.
A clear path of enabled nodes leads down to the class you want to enable. The other classes in the package are disabled (unless you individually enable them as well). An asterisk is displayed to the right of an enabled node. Tracing is enabled by resetting the program with the Run|Program Reset command.
- Choose Run|Program Reset.
- Choose Run|Debug.
The presence or absence of a forward slash on the icon for each class in the Loaded Classes window indicates whether the Debugger will trace into that class. If the slash is visible, tracing for that class is disabled. If no slash is visble, tracing is enabled. (Tracing is enabled only after you choose Run Program|Reset.)
Example
The following example enables tracing into the java.lang.String class only:
- Select the java package node, right-click, and select Disable Tracing (Trickle).
All packages and classes under the java package node are changed to Disabled, regardless of any Enabled settings for individual packages or classes.
- Select the java package node, right-click, and select Enable Tracing.
The java package node is changed to Enabled but all the packages and classes below it are still Disabled.
- Select the java.lang package, right-click, and select Enable Tracing.
The java.lang package is Enabled, but all the classes below it are still Disabled.
- Select the java.lang.String class, right-click, and select Enable Tracing.
There is now a clear path of Enabled settings down to the java.lang.String class. An asterisk appears to the right of the String class.
- To restart the Debugger and activate the new Trace Into settings, select Run|Program Reset, then Run|Debug.
Tracing Into the java.lang.String class is now Enabled.
When you set Trace Into to Enabled for a class, you can pause at a block of code in that class, display the source code in the Source pane, and manually step through the code by clicking the Trace Into and Step Over buttons. You can enable and disable Trace Into for classes and packages. "Enabling a class" means setting the Trace Into setting for that class to "Enabled." "Enabling a package" means setting the Trace Into setting for a package node to Enabled. This is different from individually enabling every class in the package.
The default setting for the sun, java, and borland.jbcl packages is Disabled. Classes that are in your own packages are Enabled by default.
Restarting the Debugger to update the Tracing Enabled settings
When you change the Trace Into settings, watch for an asterisk to the right of class names. This means for the changed settings to take effect, you need to use the Run|Program Reset command and then begin a new debugging session.
Trickling of the Tracing Enabled settings through the class hierarchy
The Loaded Classes window presents a tree in which you can enable or disable tracing into. The Loaded Classes window popup menu includes the following commands:
- Enable Tracing
- Disable Tracing
- Enable Tracing (Trickle)
- Disable Tracing (Trickle)
- View List of Non-Traceable Classes
The following illustration shows the Loaded Classes window and the popup menu:
If the Enable/Disable Tracing (Trickle) commands are selected, the given node and every package and class below it, are changed to the specified value (Enabled or Disabled).
The View List of Non-Traceable Classes command displays the List of Packages And Classes With Tracing Disabled window. This window displays the Tracing Disable list, a list of all classes for which tracing is disabled. Any class not listed in the Tracing Disabled list, or classes that are in a package that is not in the Tracing Disabled list, default to Enabled.
Setting Trace Into for classes that have not been loaded
You can disable any package or class, whether or not it's been loaded yet, using the List Of Packages And Classes With Tracing Disabled window. This window contains the Tracing Disabled list, which is independent of which classes have already been loaded so far.
To disable Trace Into for classes or packages that are not yet loaded:
- In the Loaded Classes window, right-click, and choose View List Of Non-Traceable Classes.
A window appears, called the List Of Packages And Classes With Tracing Disabled window. This window shows the list of packages and classes with tracing disabled.
- Type in the class or package name you want.
sun, java, and borland.jbcl appear in the Tracing Disabled list, but you can remove them from the list.
The Tracing Disabled list is global across projects. Trace Into settings are retained across debugging sessions and are stored in the Tracing Disabled list. The Loaded Classes tree is retained across sessions. As classes are added to the Loaded Classes window during a debugging session, the tree picks up the Enabled or Disabled settings for each class from the Tracing Disabled list.
Tracing into classes with no source available
If you have a class but not its source file (such as classes in the Sun package) and set tracing for that class to Disabled and tell the Debugger to trace into that class, the Debugger runs straight through that code without pausing and returning control to you. The Debugger pauses at the next line of code in a class for which you do have source available.
If you set a class to Enabled, and you don't have the source file for that class, a stub source file is generated and appears as you trace through your code. The stub source file shows only the method signatures for the class. To avoid seeing stub source, you can Disable the classes for which you don't have the source files available, or make their source files available.
Quickly disabling Trace Into for the main libraries
You can quickly disable Trace Into for the main libraries. Only your code or code in other libraries will be traced into as you step through your program in the Debugger.
To quickly disable Trace Into for all libraries:
- Select View|Loaded Classes.
The Loaded Classes window appears.
- Right-click in the window and select View List Of Non-Traceable Classes.
The List Of Packages And Classes With Tracing Disabled window appears.
- Type in the following library names, 1 per line:
- Click OK.
Trace Into is now disabled for these libraries. Any future loaded classes belonging to these libraries will default to Disabled.
Breakpoints and tracing disabled settings
Setting a breakpoint in a class for which Trace Into is set to Disabled overrides the Disabled setting; tracing into the class becomes Enabled as long as there is a breakpoint in the class. The debugger will trace into that class, because you explicitly instructed the Debugger to go to that point. You can view any class, even the disabled ones, in the Source pane. If you know the package name and class name, you can manually bring up that source file in the Source pane and set a breakpoint in it.