debugging techniques
This chapter contains the following debugging techniques:
using the jdb debugger
The Java™ debugger, jdb, debugs byte-code in standalone Java™ applications and applets. It provides a command line interface.
For best results, if you are using Java™ version 1.1.5.x,
turn off the JIT compiler by specifying JIT_OPTIONS="-nojit"
before invoking jdb. If you are using Java™ version 1.1.6 or later, you can
leave JIT_OPTIONS on.
To debug a standalone Java™ program on HP-UX:
- Compile it with the javac -g (debug) option.
For example:
$ javac -g ArrayException.java
- Next, invoke the jdb debugger.
For example:
$ java -version
java version "HP-UX Java™ C.01.15.05 08/06/98"
$ export JIT_OPTIONS="-nojit" Turn off the JIT compiler.
$ jdb ArrayException Start jdb.
> help List jdb commands.
> exit Quit jdb.
sample jdb debugging session
In this example, the program to be debugged is called
Average.
This program finds the average of an array of 10 integers.
You can copy this program to a file, and compile it for debugging by using
the -g option:
$ javac -g Average.java
Now run the program:
$ java Average
4
3
The results should actually be 3 and 2, not 4 and 3.
To get started, invoke the jdb debugger and load the class to be debugged:
$ jdb Average
Initializing jdb...
0xe84828:class(Average)
> stop in Average.main Set breakpoint in main.
Breakpoint set in Average.main
> run
run Average Start program.
running ...
Breakpoint hit: Average.main (Average:41)
main[1] main[1] list Show source code.
37 int i;
38
39 // Instantiate 2 objects of type Average.
40 Average Avg1, Avg2;
41 => Avg1=new Average();
42 Avg2=new Average();
43
44 // Set start and end points in arrays for both objects.
45 Avg1.low=FIRST;
main[1] list 60 Show source code.
56 for (i=FIRST; i< ="LAST-3;" i++)="i++)"
57="57" {="{" 58="58" Avg2.list[i]="my_list[i];" 59="59"}="}"
60="">
61 // Use calculate_avg methods in both objects
62 // to find Average value of arrays
63 System.out.println(Avg1.calculate_avg());
/* Prints 4 */
64 System.out.println(Avg2.calculate_avg());
/* Prints 3 */
main[1] stop at Average:63 Break at line 63.
Breakpoint set at Average:63
main[1] cont Run.
Breakpoint hit: Average.main (Average:63)
main[1] dump Avg1 Display Avg1 object.
Avg1 = (Average)0xe80c00 {
int list[] = { 3, 4, 2, ... }
int low = 0
int high = 9
}
main[1] print Avg1.list[9] Display array element.
Avg1.list[9] = 7
main[1] step Step into calculate_avg().
main[1] main[1] list
24 public int calculate_avg()
25
26 {
27 int total, num_elements, l_average;
28 => total = sum(list, low, high);
29 num_elements = high-low;
//Note, this is an off-by-1-byte bug
30 l_average = total / num_elements;
31 return(l_average);
32 }
main[1] stop at Average:31 Set breakpoint at end of method.
Breakpoint set at Average:31
main[1] cont Run.
Breakpoint hit: Average.calculate_avg (Average:31)
main[1] main[1] locals Display local variables in method.
Method arguments:
this = Average@1d0180
Local variables:
total = 36
num_elements = 9 Here's the problem; should be 10!
l_average = 4
main[1] stop Show breakpoints.
Current breakpoints set:
Average:31
Average:63
Average:41
main[1] clear Average:31 Remove a breakpoint.
Breakpoint cleared at Average: 31
. . .
main[1] cont Finish running.
main[1] 4
3
Average exited
debugging Java™ applets
To debug a Java™ applet:
- First, cd to the directory containing the HTML file for the Java™ applet.
For example, on HP-UX:
$ cd /opt/java/demo/TicTacToe
- Next, invoke the appletviewer program in debug mode:
$ appletviewer -debug example1.html
Initializing jdb...
0x7a268148:class(sun.applet.AppletViewer)
>
debugging an already running process
You can use the jdb debugger to attach to a Java™ applet or Java™ application running
in a seperate process. If you launch a Java™ application using the -debug
option, you connect to the virtual machine by using jdb in another console
session or window. To launch a Java™ process to be debugged in this way:
-
In one window, start the Java™ interpretter using java_g -debug.
The Java™ interpretter will return a session-specific password for debugging.
For example:
$ export JIT_OPTIONS="-nojit"
$ java_g -debug myclassfile
Agent password=5i8tp4
The java_g command invokes a debug version of the Java™ virtual
machine.
The application to be debugged starts executing immediately. This program
must pause for user input or another external event, in order for you to
initiate the next step. Otherwise, the program may run to completion.
-
To connect to the Java™ process started in step 1, open a second window
and start jdb using the password from step 1:
$ jdb -password 5i8tp4
. . initializing jdb...
debugging native methods
Java™ main programs can call C or C++ routines and C or C++ main programs
can call Java™ code. Methods implemented in a language other than Java™ are called native methods.
Calls between Java™ and C or C++ are made
by using Java™ Native Interface (JNI).
To debug C or C++ native methods, use the HP Wildebeest Debugger
(HP WDB). This debugger is an HP-supported implementation
of the gdb debugger. HP DDE also supports debugging
of native methods, but for best results, use HP WDB.
Debugging Shared Library Code with HP WDB (gdb)
In this example, the Java™ program is named
TestJavaCallingNative. This program calls a C native method named
Java_TestJavaCallingNative_sayHelloWorld.
To view the example source code,
see /opt/java/docs/hpux/HPUX_JNI.html.
To debug native methods in shared libraries called by Java™ programs, follow these
steps:
- Verify that you have HP WDB version 0.75.04 or later.
$ gdb -version
You can download HP WDB from HP for no charge.
- Compile your Java™ source files with the -g debug option. For
example:
$ javac -g TestJavaCallingNative.java
- Use javah to create native method header files. For example:
$ javah -jni TestJavaCallingNative
- Compile your C or C++ code with the -g option. The following example
additionally compiles for the kernel-threaded JVM:
$ export JNI_INCLUDE="-I/opt/java/include
-I/opt/java/include/hp-ux"
$ cc -g -Ae +u4 +z -c $JNI_INCLUDE -DNATIVE
-D_POSIX_C_SOURCE=199506L cImpl.c
Or, compile for a user-threaded JVM:
$ cc -g -Ae +ur +z -c $JNI_INCLUDE -D_HPUX cImpl.c
- Build the shared library for the C or C++ routines. For example:
ld -b -o libcImpl.sl cImpl.o
- Create a shell script to load gdb. You can use the following script,
called mygdb, as an example:
#!/bin/ksh
# This script is usually invoked as
# mygdb java <arguments to="to" java="java">
#
JAVA_ARGS=/tmp/java_args.$$
EXECNAME=$1
GDB=/opt/langtools/bin/gdb
#
# move past the VM name itself (1st argument
= usually "java")
shift
#
# put the arguments to java in the java arguments
file trap "rm -f $JAVA_ARGS"
0 1 2 3 4 8 15
#
echo "set args" "$@" > $JAVA_ARG
#
$GDB $GDBOPTS --command=$JAVA_ARGS $EXECNAME
#
- Set the environment variable DEBUG_PROG to point to the
location of your mygdb script.
$ export DEBUG_PROG=/projects/working/mygdb
- Run your Java™ main program and begin debugging
your C or C++ native code with gdb:
$ chmod +x mygdb
$ java JavaCallingNative cImpl
:
:
(gdb) break Java_TestJavaCallingNative_initialize
Breakpoint 1 (deferred) at
"Java_TestJavaCallingNative_initialize"
("Java_TestJavaCallingNative_initialize"
was not found). Breakpoint deferred until a shared
library containing "Java_TestJavaCallingNative
_initialize" is loaded.
(gdb) run
Starting program: /opt/java/bin/PA_RISC/
green_threads/java TestJavaCallingNative cImpl
Library cImpl successfully loaded
initialize C++ runtime (nop for C)
Breakpoint 1, Java_TestJavaCallingNative_initialize
(env=0x7ad4a274, class=0x3) at cImpl.c:7
7 }
Debugging Shared Library Code with HP DDE
HP DDE supports the debugging of native methods written in C and C++.
To debug native methods in shared libraries called by Java™ programs,
follow these steps:
-
Compile your Java™ and C or C++ source files with the -g debug
option and build your test application. (See steps 2-5 under
"Debugging Shared Library Code with HP WDB (gdb).")
-
Set the DEBUG_PROG environment variable to
dde.
$ export DEBUG_PROG="/opt/langtools/bin/dde"
-
Run your Java™ application. For example:
$ java TestJavaCallingNative cImpl
The HP DDE main menu appears.
-
In HP DDE, type init -alt in the Debugger Input window.
dde> init -alt
This loads all Java™ binary symbols.
-
Type bre __map_dld (--use a double underscore before map--),
followed by go in the Debugger Input window:
dde> bre __map_dld
dde> go
Break at: \\__map_dld # `va(00003204)
This stops the debugger after the dynamic loader, dld initializes events.
The __map_dld symbol is defined in the crt0 program startup file.
-
Type go -return in the Debugger Input Window.
Stopped at: \\$START$ (0000306C)
This causes the debugger to stop immediately after it loads shared libraries.
-
Type prop lib nativemethodlib -add in the Debugger Input window.
For example:
dde> prop lib libcImpl.sl -add
Loading symbol information for
"/home/gene/JavaCallingNative/libcImpl.sl".
This causes the debugger to open the shared library and make symbols available for setting
breakpoints.
-
Type int load, followed by go:
dde> int load
dde> go
Intercepted event type "load ".
Library loaded by process 9763:
"/home/gene/JavaCallingNative/libcImpl.sl".
This command generates a debug inteinterruptn a shared library is loaded. The
debugger displays the shared library name when it finishes loading it.
-
You can now begin setting breakpoints in your shared library code. For example:
dde> bre Java_TestJavaCallingNative_sayHelloWorld
dde> go
Library cImpl successfully loaded
debugging tip
You can combine the above debugging commands, shown in steps 4-9, on one command line:
init -alt ;bre __map_dld -do [go];int load -do
[bre Java_TestJavaCallingNative_sayHelloWorld ] ;
prop lib libcImpl.sl -add;go
jdb quick reference
To set a breakpoint:
stop in class.main
stop in class.method
stop at class:line #
To run the program:
run
To list source code:
list
list line #
To display variables:
locals
print variable
dump variable
To continue running:
cont
To step through program:
step (to next line)
next (step over calls)
step up (run until method returns to caller)
stepi (to next instruction)
To list breakpoints:
stop
clear
To clear a breakpoint:
clear class:line #
To list threads:
threads (shows application threads)
threadgroup system
threads (shows all threads)
To list methods in executing class:
methods
To show a stack trace:
where
|
Java™ and all Java-based trademarks and logos are trademarks or registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. Hewlett-Packard is independent of Sun Microsystems, Inc.
|
|