Tools Guide  

Chapter 12   Debugger

The SilverStream Debugger lets you find runtime errors in your Java applications by controlling and monitoring the execution of Java code. You can debug server-side objects (such as J2EE applications) and client-side objects, either on a local host machine or remotely on distributed machines.

NOTE   By default, when you launch a debugger from within Workbench, the SilverStream Debugger is launched. If you want to use a different debugger, you can specify that debugger so it is launched from within Workbench. For more information, see "Specifying a debugger" on page 41.

This chapter describes the following:

 
Top of page

Concepts you need to know

You should review the following concepts before you use the Debugger.

Concept

Description

Breakpoint

You can set a breakpoint on an executable line in your code where you want execution to stop temporarily. When you set a breakpoint in code, the program stops running before executing the line containing the breakpoint, then turns control over to the Debugger.

Deadlock

A deadlock is a condition that occurs when two processes are each waiting for the other to complete before proceeding. Both processes hang.

Instance variable

An instance variable is a field declared within a class declaration without using the keyword static.

Local variable

A local variable is declared inside a particular method. Only code that is contained in the method can access a local variable.

Monitor

In Java, a monitor is an exclusive lock on an object. Locks are used in thread synchronization.When a method is programmed to be synchronized, it cannot be run in multiple threads concurrently. When a synchronized method is entered, it acquires a monitor on the current object (the object whose method was called). The monitor prevents other synchronized methods in the object from executing. When the synchronized method returns, its monitor is released, allowing other synchronized methods in the same object to run.

Thread

A thread is a single execution stream in a program. Java is a multithreaded language, which means that you can have many execution streams operating at one time. In Java, threads are represented by the Thread object.

 
Top of page

About the Debugger

The SilverStream Debugger provides several capabilities for diagnosing problems with your Java applications.

Here is a sample Debugger window, showing many of its features:

Debugging server objects and client objects  

You can debug the following objects:

Server objects

Objects in deployed J2EE applications:

  • Servlets (including compiled JavaServer Pages)

  • Enterprise JavaBeans

  • Other Java code in deployed J2EE archives

Other Java applications executing on a server

Client objects

Client Java applications, including J2EE application clients

Local and remote debugging   With the SilverStream Debugger you can troubleshoot Java applications running on a local host or remotely in a distributed network. You can configure a process to be debugged either on the local machine or on a remote machine, but not for both in the same session.

There are many situations that require remote debugging. For example:

Controlling program execution   The Debugger provides methods for exercising your code by:

Monitoring program status   To help you isolate problems in source code, the Debugger provides viewers for examining variables, the call stack, and thread status at any point in program execution.

Typical workflow for debugging   Although each debugging session poses its own unique challenges, you typically follow this workflow when troubleshooting applications:

Debugging server and client applications   The techniques you use to debug applications running on a server as opposed to client applications are different. The next two sections describe the techniques:

 
Top of page

Debugging server applications

If you are debugging objects running on a server (such as J2EE applications), you should start the application on your server and then attach the Debugger to that application, rather than trying to start the application from the Debugger. You can debug applications running on any J2EE application server supported by Workbench.

 
Top of section

Starting the server

In some cases, you must start your application server in debug mode before you can debug server objects. This section provides instructions for starting the SilverStream eXtend Application Server and BEA WebLogic for debugging.

    For further details about starting these and other application servers in debug mode, consult the documentation for the server.

Starting the SilverStream server for debugging

To start the SilverStream eXtend Application Server for debugging:

Examples   This command line launches the SilverStream server for local debugging:

  ServerInstallDir\bin\SilverServer +debug

This command line launches the SilverStream server for remote debugging:

  ServerInstallDir\bin\SilverServer +debugremote

Starting the WebLogic server for debugging

To start WebLogic for debugging:

  1. Modify your startWebLogic.cmd file by adding the options in bold to the command line for starting the server:

      "%JAVA_HOME%\bin\java" -hotspot -ms64m -mx64m -Xdebug -Xnoagent
      -Xrunjdwp:transport=dt_socket,server=y,suspend=n -Djava.compiler=NONE
      -classpath ...
    
  2. Start the server.

    When starting, the server will display the debug address:

      Listening for transport dt_socket at address: address
    

    You will use this value when launching the Debugger, as described next.

 
Top of section

Launching the Debugger

You can launch the Debugger from within Workbench or from the command line.

To launch the Debugger from Workbench:

  1. Select Edit>Launch Debugger.

  2. Select Attach to running process.

  3. If debugging an application on a local server, select Shared Memory Debugging and provide the debug address.

    If debugging an application on a remote server, select Remote Socket Debugging and specify the machine name and debug port.

    NOTE   If debugging an application running on WebLogic, even on a local WebLogic server, select Remote Socket Debugging and specify the machine name (localhost if local) and the address (port) the server reported when starting.

  4. Open files you want to debug in the Debugger, set breakpoints, then run your application.

To launch the Debugger from the command line:

  1. Make current the WorkbenchInstallDir\bin directory.

  2. If debugging an application on a local server, enter:

      SilverDebugger -attach localhost debug_address
    

    If debugging an application on a remote server (or a local WebLogic server), enter:

      SilverDebugger -attach machine_name:debug_port
    
  3. Open files you want to debug in the Debugger, set breakpoints, then run your application.

Now you are ready to manage program execution and analyze the behavior of your application.

 
Top of section

A sample debugging session

In the following scenario, you'll see how to debug ProverbFinal, the J2EE application that is built in the Workbench's Web application tutorial. The scenario shows debugging the application on a local SilverStream server. (This application is provided as a Workbench project. For details, see Tutorials in the Workbench help.)

  1. Start the local server in debug mode.

      ServerInstallDir\bin\SilverServer +debug
    
  2. Open the ProverbFinal project in Workbench.

    The project is in WorkbenchInstallDir\docs\tutorial\ProverbFinal. It is a completed application.

  3. Deploy the application to the server.

    In this scenario, the application was deployed to ProverbsCloud, the Cloudscape database provided with the tutorial.

  4. Open the file to be debugged.

    If you have a file open when you launch the Debugger from Workbench, that file opens in the Debugger automatically. You can also open other files in the Debugger to debug them.

    Here, TodayAction.java was opened. This code is executed when someone asks to see today's proverb.

  5. Select Edit>Launch Debugger to start the Debugger.

  6. Specify the following:

    Because the SilverStream server was started using the default debug address, agsrv was specified as the debug address.

    The Debugger opens and displays the file.

  7. Set a breakpoint on a line of code by placing the cursor on the line and clicking the Toggle Breakpoint icon in the Debugger toolbar:

  8. Run the application. To do that, open a browser and specify this URL:

      http://localhost/ProverbsCloud/ProverbFinal/index.jsp
    

  9. Click Today's Proverb. This action invokes code in TodayAction.java. Execution stops (you will see that the browser has not completed processing the page) and the Debugger window is updated.

    You can see that the execution arrow is at the breakpoint.

  10. At this point, step through the code, looking at variable values, the call stack, and so on, as described in the rest of this chapter.

  11. When finished debugging, continue execution by clicking the Continue icon:

    The page completes execution.

 
Top of section

Debugging J2EE applications

Using the techniques shown in the preceding sample debugging session, you can debug your J2EE applications. You debug EJBs and servlets exactly as shown above: open the source code for the EJB or servlet in the Debugger, set one or more breakpoints, then run your application.

Debugging JSP pages

To debug a JSP page, which is translated and compiled into a servlet for execution, you need to locate the Java source file that the server created from the JSP page, open the source file in the Debugger, and set your breakpoints. Different J2EE servers will locate their source files differently. Here is information about the SilverStream eXtend Application Server and WebLogic:

Server

Description

SilverStream eXtend Application Server

The SilverStream server locates its generated source files in its compile cache.

To find the Java source files the SilverStream server generated from deployed JSP pages, look in this directory:

  ServerInstallDir/compilecache/server/database/temp/sources/application/com/sssw/gen/jsp

For example, to find the source file corresponding to today.jsp, shown above, look in:

  ServerInstallDir/compilecache/localhost/ProverbsCloud/temp/sources/ProverbFinal/com/sssw/gen/jsp

You will see a set of .java files corresponding to the JSP pages that the server translated into servlets. Files will be named name_jsp_nnnnnnnnnn.java.

WebLogic

By default, WebLogic does not save the Java source files generated from JSP pages. To instruct WebLogic to keep the generated Java source code for your JSP pages, specify the value true for the keepgenerated parameter in the jsp-descriptor element in weblogic.xml.

    For information about other servers, consult their documentation.

To debug a JSP page, open its corresponding .java file in the Debugger, set a breakpoint, and run the JSP page. Execution will stop, and you can examine your JSP page.

Here, execution has stopped in the Java source file generated from today.jsp:

 
Top of page

Debugging client applications

In addition to debugging J2EE applications and other applications running on application servers, you can also use the Debugger to debug client Java applications.

When debugging client applications, you can either invoke the Debugger to start the application or attach the Debugger to a running application.

 
Top of section

Invoking the Debugger to start the application

You can start an application from within Workbench or from the command line.

To start a client application from Workbench:

  1. In Workbench, open the project that defines the application.

    Make sure the project's classpath is set up correctly.

  2. Open the Java source file you want to debug.

  3. Select Edit>Launch Debugger.

  4. Select Launch new process.

  5. Specify the class to execute and specify any needed arguments.

  6. Click OK.

To start a client application from the command line:

  1. Make current the WorkbenchInstallDir\bin directory.

  2. Enter the following at the command line:

      SilverDebugger [options] class class_arguments
    

    These are the SilverDebugger arguments for launching an application:

    Argument

    Description

    options

    –sourcepath directory_list

    The list of the directories (separated by semicolons) the Debugger searches for source files

    NOTE   These directories must be source tree roots

    –sourcefile filename

    The fully qualified name of the Java source file to display in the Debugger

    –?

    Display usage information for the SilverDebugger command

    –classpath directory_list

    The list of the directories (separated by semicolons) the Debugger searches for Java classes used in the application

    –Dname=value

    A system property setting for the application environment

    –Xoption

    A JVM option for the application environment

    class

    The name of the class to debug

    class_arguments

    Arguments to pass to the main() method of class

    NOTE   If your source and class files reside on remote network machines, specify paths and file names using Universal Naming Convention (UNC) format:

      \\server-name\shared-resource-pathname
    

    For example, to debug the demo Notepad application that comes with the JDK, enter this command (where InstallDir is the installation directory for the demo application, such as c:\jdk1.3\demo\jfc\Notepad):

      SilverDebugger -sourcepath InstallDir\src 
                     -sourcefile InstallDir\src\Notepad.java 
                     -classpath InstallDir\Notepad.jar 
                     Notepad
    

    The Debugger opens on your desktop displaying the Java source file specified.

  3. Set one or more breakpoints in your code or in exceptions.

  4. Select Tools>Continue from the menu or click the Continue icon in the toolbar of the Debugger window:

    The application opens on your desktop and execution stops at the first breakpoint encountered.

Now you are ready to manage program execution and analyze the behavior of your application.

 
Top of section

Attaching to a running application

You can also start the application, then attach the Debugger to it. To do this, you must start the application specifically for debugging.

To attach the Debugger to a running Java application:

  1. Launch the Java application either on the local host or on a remote machine:

    To launch the application on the local host:

    The JVM returns a debug address. For example:

    In this example, the JVM returns javadebug as the debug address. The option transport=dt_shmem specifies shared-memory transport, which is required for local debugging.

    To launch the application on a remote network machine:

    The JVM returns a debug port number. For example:

    In this example, the JVM returns 3340 as the debug port. The option transport=dt_socket specifies socket-based transport, which is required for remote debugging.

  2. Invoke the Debugger either from within Workbench or from the command line.

    To invoke the Debugger from within Workbench:

    1. Select Edit>Launch Debugger.

    2. Select Attach to running process.

    3. If debugging locally, select Shared Memory Debugging and specify the debug address returned by the JVM. If debugging remotely, select Remote Socket Debugging and specify the debug port returned by the JVM.

    To invoke the Debugger from the command line:

    The Debugger opens on your desktop.

  3. Open a source file for debugging using File>Open.

Now you are ready to manage program execution and analyze the behavior of your application.

Debugging against SilverJRunner or SilverJ2EEClient   This is just like debugging against a SilverStream server. You launch SilverJRunner or SilverJ2EEClient with an appropriate debug startup option (described in Starting the server), then attach the Debugger to the resulting debug address (default is agjrn) or debug port (default is 9901).

 
Top of page

Managing program execution

Once you have started the Debugger, there are several ways to manage program execution to allow you to isolate and diagnose problems in the source code:

 
Top of section

Using breakpoints

You use breakpoints to specify lines in your code where you want to stop execution and give control to the Debugger. When the code stops executing and the Debugger takes control, you can execute Debugger commands and view the call stack, thread status, and variable values.

You can set breakpoints only on individual lines in your code. If a line contains multiple statements, you can set a breakpoint only on the first statement in the line. To set breakpoints on the subsequent statements, you need to break up the line so that each statement appears on its own line.

NOTE   Breakpoints are stored by server name and class name. As a result, like named objects on the same server share breakpoints.

Setting and removing breakpoints in code

There are several ways to set and remove breakpoints in code, either for local classes or classes loaded from external sources. If the Debugger cannot find the source code, it prompts you for a path, as described in When the Debugger cannot locate source code.

This section describes the procedures for setting and removing breakpoints in source code.

To set breakpoints in code using Toggle Breakpoint:

  1. Put the cursor at the line in the source code where you want to set a breakpoint.

  2. Either choose Tools>Toggle Breakpoint from the menu or select the Toggle Breakpoint icon in the Debugger toolbar:

    The breakpoint indicator appears in the left margin beside the line you specified.

To set breakpoints in code using the Edit menu:

  1. Select Edit>Show Line Numbers from the menu.

    This makes it easier to specify locations for breakpoints.

  2. Choose Edit>Breakpoints from the menu.

    The Manage Breakpoints dialog opens.

  3. Select the Code tab.

    The dialog lists all breakpoints that have been set.

  4. Click Add.

  5. Do one of the following:

    To insert a breakpoint in

    Do this

    Your local Java class

    1. In the Specify Breakpoint field, enter the location where you want to add a breakpoint, in this form:

        <fully qualified class name>:<line number>
      

      Example:

      com.myapp.gui.CheckBoxes:99

    2. Click OK.

    Loaded classes

    1. Click Browse.

    2. Navigate to the method where you want to insert a breakpoint and click OK.

      The breakpoint specification appears in the Specify Breakpoint field.

    The new breakpoint appears in the Manage Breakpoints dialog.

  6. Click OK.

  7. Click Done to add the breakpoint to the source code.

To remove individual breakpoints using Toggle Breakpoints:

  1. Click in a line that has a breakpoint.

  2. Select the Toggle Breakpoint icon in the Debugger toolbar.

To remove breakpoints using the Edit menu:

  1. Choose Edit>Breakpoints from the menu.

    The Manage Breakpoints dialog opens.

  2. Select the Code tab and click to select the breakpoints you want to remove.

  3. Click Delete.

    The breakpoints disappear from the list in the Manage Breakpoints dialog.

  4. Click Done.

    The breakpoints disappear from the source code.

To remove all breakpoints:

Setting and removing breakpoints in exceptions

In addition to setting breakpoints in the main body of source code in your Java applications, you can set breakpoints in standard Java exceptions or in exceptions that you write to handle specific behaviors.

This capability can help you pinpoint the source of exceptions that are thrown unexpectedly when you run your application. When you set a breakpoint in an exception and then run your application, the Debugger will stop where the exception gets thrown and display the offending source code if it is available for the class you are debugging. If the Debugger cannot find the source code, it prompts you for a path, as described in When the Debugger cannot locate source code.

To set breakpoints in exceptions:

  1. Choose Edit>Breakpoints from the menu.

    The Manage Breakpoints dialog opens.

  2. Select the Exception tab and click Add.

    The Add Exception Breakpoint dialog opens.

  3. Type the fully qualified name of the exception class on which you want to break, or click Browse to select an exception from the list of loaded exceptions.

  4. Click OK to return to the Manage Breakpoints dialog.

    The new breakpoint is listed.

  5. Click Done.

    NOTE   Exception breakpoints do not appear in the source code.

To remove breakpoints from exceptions:

  1. Choose Edit>Breakpoints from the menu.

    The Manage Breakpoints dialog opens.

  2. Select the Exception tab and click the breakpoints you want to remove.

  3. Click Delete.

    The breakpoints are removed from the list.

  4. Click Done.

Enabling and disabling breakpoints

The Debugger allows you to enable and disable breakpoints in code and exceptions. Disabled breakpoints appear with a grayed icon:

To enable breakpoints:

  1. Select Edit>Breakpoints from the menu.

    The Manage Breakpoints dialog opens.

  2. Select the Code or Exception tab to locate the breakpoints you want to enable.

  3. Click the breakpoints you want to activate and click Enable.

  4. Click Done.

    The breakpoints you selected will be enabled when you continue program execution.

To disable breakpoints:

  1. Select Edit>Breakpoints from the menu.

    The Manage Breakpoints dialog opens.

  2. Select the Code or Exception tab to locate the breakpoints you want to disable.

  3. Click the breakpoints you want to activate and click Disable.

    To select multiple breakpoints: hold down the Ctrl or Shift key when you click each choice.

  4. Click Done.

    The breakpoints you selected will be disabled when you continue program execution.

 
Top of section

Continuing execution

When the program stops at a breakpoint you can continue execution using the Continue or Run to Cursor commands in the Debugger:

When the program reaches a breakpoint, the Debugger window is activated and an arrow (called the execution pointer) appears in the margin to the left of the code indicating which line is about to be executed.

Along with the execution pointer, the Debugger displays a list of local and instance variables and enables the commands for stepping through your code.

To continue execution:

To run to a specified location in the source code:

  1. Click in the line of code where you want execution to stop.

    The cursor must be located on a line that contains executable statements.

  2. Select Tools>Run to Cursor from the menu or click the Run to Cursor icon in the toolbar of the Debugger window:

    Run to Cursor executes your code from the current execution location until it reaches the place where the cursor is located. If you have breakpoints set and a line containing a breakpoint is executed before the line that has the cursor, Run to Cursor stops execution at that breakpoint line.

    NOTE   If you put the cursor on a line that doesn't get executed—for example, if your cursor is on the first line of code inside an if statement when the if condition evaluates to false—the effect of executing Run to Cursor will be the same as if you select the Continue command.

 
Top of section

Stepping through the code

There are three Step commands included in the SilverStream Debugger:

Command

Executes

Details

Step Over

The current line

If the current line contains a method call, that method is executed. The Debugger stops at the line immediately following the line that was executed.

Step In

The current line

If the current line contains a method call, the Debugger stops at the first line in the called method. Otherwise, the Debugger stops at the line immediately following the line that was executed.

If the Debugger cannot find the source code for the method it has entered, it prompts you for a path, as described in When the Debugger cannot locate source code, next.

Step Out

The remainder of the current method

The Debugger stops at the statement immediately following the statement that called the current method.

 
Top of section

When the Debugger cannot locate source code

When the Debugger cannot locate source code for a particular operation, it prompts you to provide the path to the source file. Either provide the path or dismiss the prompt and follow directions to either continue execution or step out of the current method.

 
Top of page

Analyzing the behavior of the application

You can examine the current execution state at three points:

At each of these points you can view the following information:

 
Top of section

Viewing the call stack

The Debugger provides a viewer that lets you examine the call stack during program execution. The call stack viewer shows the name of each method in the stack, along with its source file and line number.

When you double-click a method in the call stack viewer, the source file opens in the Debugger, highlighting the line where the method is called. If the Debugger cannot find the source file, it prompts you for a path, as described in When the Debugger cannot locate source code.

The call stack viewer updates the call stack when:

To open the call stack viewer:

 
Top of section

Viewing threads

The Debugger provides a viewer that lets you examine the status of threads during program execution. The thread viewer displays threads organized by groups, showing the name of each thread, along with its identifier and state.

You can suspend and resume threads to isolate problems that occur in thread synchronization, such as deadlocks and infinite loops.

The thread viewer updates thread status when:

To open the thread viewer:

Interpreting thread states

Threads can exhibit a variety of states during program execution:

Thread state

Description

At breakpoint

Thread was running when execution stopped at the breakpoint

Running

Thread is running

Sleeping

Thread is sleeping for a specified period of time

Suspended

Thread is suspended

Waiting

Thread is waiting for notification to resume running

Waiting on monitor

Thread is waiting for a monitor to be released by another thread

NOTE   In a deadlock situation, you will see two or more threads in this state. However, threads that appear in this state do not necessarily indicate a deadlock.

Suspending and resuming threads

If you encounter an infinite loop or deadlock in a thread, you can isolate the problem by suspending the thread and viewing its call stack. You cannot view the call stack of a thread unless it is suspended.

To suspend a thread and view its call stack:

  1. Open the thread and call stack viewers.

  2. Do one of the following:

    To suspend

    Do this

    All threads

    1. Stop execution of the code at a breakpoint.

    2. Click the suspended thread.

    An individual thread

    Double-click a running or waiting thread in the thread viewer

    The call stack for the selected thread appears in the call stack viewer.

  3. Double-click methods in the call stack to view their code in the Debugger.

    If you double-click a waiting thread, the method that put the thread in a wait state appears in the call stack viewer.

    If the Debugger cannot locate the source code for a method you selected, it prompts you to supply a path, as described in When the Debugger cannot locate source code.

To resume a thread:

 
Top of section

Viewing variables

The Debugger provides a viewer that lets you examine local and instance variables when program execution stops at a breakpoint. The variable viewer displays the variable name, type, and value.

The variable viewer updates variable values when:

To open the variable viewer:

  1. In the Debugger, choose View>Variables from the menu.

    A pane for viewing variables appears in the Debugger window.

  2. Click locals to view local variables and click this to view instance variables for the current object.

 
Top of page

Debugger keyboard shortcuts

Use these keyboard shortcuts.

Keystroke

Description

Ctrl+C

Copy to Clipboard

Ctrl+G

Go to line number

Ctrl+F

Find/Replace

F5

Continue

F10

Step over

F11

Step in

Shift+F11

Step out

Ctrl+F10

Run to cursor


   

Tools Guide  

Copyright © 2002, SilverStream Software, Inc. All rights reserved.