Controlling program execution

The most important characteristic of a debugger is that it lets you control the execution of your program; 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 and has a green arrow to the left. 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 Thread and Stack pane, and choose Run|Show Execution Point. The Debugger displays the block of code containing the execution point. If the source code is not available, a message appears. 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 Trace Into and 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.

Trace Into

The 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:

Step Over

The Step Over command, like 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.

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.

There are several ways to issue the Step Over command:

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.

When you are using the Debugger, your program can be in one of two possible states: running, or paused by the Debugger. 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 by the Debugger, 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 that source code can be shown, because you don't have tracing enabled, the Debugger continues processing without pausing, until it finds a piece of code that it can trace into.

Typically, when 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 Run To Cursor, you can have multiple breakpoints in your code. You can customize each breakpoint so it pauses the program execution only when certain conditions occur.

See also:
Using breakpoints

Running to the end of a method

The Run To End Of Method menu item 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:

  1. In the Source pane, position the cursor on the line of code where you want to begin (or resume) debugging.
  2. Run to the cursor location using one of the following methods:
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

Sometimes while debugging, you will find it necessary 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, select Run|Program Reset (or press Ctrl+F2).

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 Thread 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:

The Thread 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:

  1. 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.
  2. Move the cursor in the Source pane to a position completely past the call.
  3. Set a breakpoint.
  4. Select Run | Run to run to that breakpoint.

Viewing the Execution Log

The Execution Log shows a record of events that have occurred so far during the current debugging session.

To open the Execution Log:

To control which types of information are included in the Execution Log:

  1. Right-click in the Execution Log window, and select Properties.
    The Log Properties dialog box appears.

  2. 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:

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.



Glyphs for the Loaded Classes window

  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 in the Loaded Classes tree, the Tracing Disabled list will be automatically updated, and vice versa.

To enable Trace Into for a class that has been loaded:

  1. Select View|Loaded Classes.
    The Loaded Classes window appears.
  2. Expand the package so you can see a path from the top level of the package down to your class.
  3. 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.
  4. 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).
  5. Choose Run|Program Reset.
  6. Choose Run|Debug.

The presence or absence of a slash on the icon for each class in the Loaded Classes window indicates whether the Debugger will trace into that class. If you Disable a class, the slash comes back. The slash through the icon on the loaded classes window means the Debugger won't trace into that class, versus "Enabled", where the slashes go away.

Example:  Enabling tracing into the java.lang.String class only:

  1. Select the java package node, right-click, and select Disable Tracing Trickling.
    All packages and classes under the java package node are changed to Disabled, regardless of any Enabled settings for individual packages or classes.
  2. 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.
  3. 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.
  4. 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.
  5. 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 browser window, 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, which is different than individually enabling every class in the package.

The default setting is Disabled, for the Sun and Java packages, except for the Borland JBCL library and the classes that are in your own packages. Whether or not you go into a piece of code, at the point that it's loaded, it shows up in the View | Loaded Classes window. By default, tracing is Enabled for the classes in your project.

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 Program Reset and Run | Debug to start 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 pop-up menu includes the following commands:

Trickling means for a given node, and every package and class below it, change the setting of each of those nodes to the specified value (Enabled or Disabled).

All classes and packages are assumed to be Enabled. This default is overridden by the Tracing Disabled list. Any classes 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; it's independent of the Loaded Classes window.

To disable Trace Into for classes or packages that are not yet loaded:

"sun", "java", and "borland" appear in the Tracing Disabled list, but you can remove them from the list.

Whether or not a package is enabled, the future loaded classes in that package are disabled.

The Tracing Disabled list is global across projects. Trace Into settings are retained across debugging sessions; they 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 the Sun package, and you set that class to Disabled, if you tell it 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 tracing 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 tracing into for all libraries:

  1. Select View | Loaded Classes.
    The Loaded Classes window appears.
  2. Right-click in the window and select View List Of Non-Traceable Classes.
    The List Of Packages And Classes With Tracing Disabled dialog box appears.
  3. Type in the following library names, 1 per line:
  4. 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 set the Debugger to go to that point. You can view any class, even the disabled ones, in the browser window. 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.