Bdbj (version 1.1, August 2001)
Bdbj is a debugger for programs written in pure Java,
which allows the user to step both backwards and forwards through the code.
Conventional debugging concepts such as breakpoints and watches are
also supported. The debugger can be used with a command line or a graphical
interface. In the latter case there is support for editing and compiling
the source code.
Bdbj was designed and implemented by Jonathan Cook, University of Edinburgh.
For information regarding the aims and implementation of this project
see http://www.dcs.ed.ac.uk/home/jjc/
Bdbj is based on a modified version of the Kaffe (version 1.0.6) implementation of the
Java Virtual Machine, which allows the debugging
of programs which Kaffe 1.0.6 is capable of running. Kaffe supports Swing 1.1.
Running Bdbj
To run Bdbj enter the command
bdbj[tty] <classname> [<files>]
where you include the tty
to use the command line interface.
The command line interface has no support for editing or compiling.
If you specify no files, then the file <classname>.java is
automatically opened.
If the file <classname>.java does not exist you will be given
the declaration of the main function, to modify in order to create
an application.
If there are any filenames specified, then only the filenames specified
will be loaded, so it is necessary to explicity add <classname>.java.
The classname
argument must not have the .java
extension, but the file or files specified must be genuine filenames,
relative to the current directory or absolute. When using the command
line interface the filename must be of the form <package>/<classname>.java,
for example java/util/Vector.java
.
Naturally, all the classes involved must be reachable from the bdbj classpath
(see next section).
Environment Variables
Usually, you should not need to alter these, by you may wish to.
- BDBJCLASSPATH: the classpath that it used for the program to be debugged,
in contrast the CLASSPATH environment variable is relevant to running the
debugger (which is written partially in Java).
- BDBJOPTIONS: extra command line options to be passed to Kaffe when the
program to be debugged is run. You can use this to increase the stack
or heap size. Also you can add the option
-nogcJJC
which turns off all garbage collection, but if you do this your program
must not explicitly call the garbage collector.
- BDBJCOMPILE: the java compiler command to use. The default is
javac -g
, but you may find it helpful to change this
to another compiler or to one of your own shell scripts.
If you do write a shell script to be called in this way, it is essential
that the script declares which shell is to be used, by the first
line of it being #! /bin/sh
for example.
Disclaimer
Bdbj is still under development and we can accept no responsibility for
averse consequences arising from any aspect of its use.
Command Line Instructions
When you start bdbjtty you put a class name and optionally files
on the command line, you have the option to alter these before
starting debugging proper. First you are in Setup mode with the
following commands:
- class <string> : set classname.
- file <string> : add classname to list of files to be debugged.
- args <string> : set arguments.
- init <integer> <string> : set initial method's first line and file classname (see Debug Method, below)
- buffer <integer> : set the buffer size.
- start : change to Debugging mode.
- end/exit/quit/terminate : exit.
- help : display help message.
Having entered the command "start" you are transferred to Debugging
mode with the following commands:
- step : step forwards to the next line.
- stepover : step forwards one line without stepping into methods.
- back : step backwards one line.
- backover : step backwards one line without stepping into methods.
- bpt : run forwards until the next breakpoint.
- backbpt : run backwards until the last breakpoint.
- allstep : all threads step.
- Similarly allstepover, allback, allbackover, allbpt, allbackbpt.
- allotherbpt : threads other than current run to breakpoint.
- thread <integer> : change current thread.
- watch <string> : query the value of a given variable.
- toggle <integer> <string> : toggle the breakpoint status of line in file.
- listbpts : list the breakpoints set.
- clearallbpts : clear all breakpoints.
- end/exit/quit/terminate : exit.
- help : display help message.
- input <string> : send line to stdin.
There are a number of ways in which the debugger will reply:
- new-thread 0 main: thread 0 has started, its name is "main".
- line 3 in-file NewClass on-thread 0 main: we have reached line 3 in file NewClass.java and
are currently running on thread 0, whose name is "main".
- thread-dead 0: thread 0 has died.
- watch x == 1: the value of variable x is 1
The Graphical Interface
The top half of the screen shows the source code.
Below that is the status bar, and below that the watch table.
There is a slider between the status bar and watch table which
can be used to resize these components.
To the top left is a source file chooser and to the bottom left
is a "current thread being debugged" chooser.
The status bar states the class name of the file being
edited, whether the file has been modified since the last save
or compile,
whether you are in debugging or editing mode and the
line number the caret is on. "Compiled" means that the
code has not been altered since the last compile.
"Modified" means that the code has been altered since
the last save. "Uncompiled" means that the code has
been modified and saved, but not recompiled.
You are permitted to save without compiling, but never to
compile without saving. All that really matters is that if
you try to debug and the status is "Modified" or "Uncompiled",
you will be asked whether you want to recompile first, and only
allowed to debug if you do so.
Breakpoints are indicated by cyan highlighted lines, and
current lines of execution by green. If multiple threads
are running the current location of each thread is shown in
green. If control passes into another file or you change the
current thread, you will be taken automatically to the correct
location in the correct file.
The watch table initially has only two rows. Watch variables
are entered in the left hand column. A watch variable is
only registered after return has been pressed or the mouse clicked
outside the variable text field or the focus moved to another
cell of the table. The table grows to accommodate new watch variables.
If at any point you add a line to or remove a line from the source code
in a file, all breakpoints in that file are cleared. If you are
debugging and you add or remove a line, then the debugging session is
terminated. This is because if lines are added or removed, the recorded
line numbers for the program being debugged will be wrong and the debugger
will begin highlighting the wrong lines. You can, however, alter
individual lines during debugging in any way you wish,
for example to add a comment, and continue debugging.
File Menu
The title for each menu item states the name of the menu item,
the shortcut key,
then whether it is enabled in editing mode and whether
it is enabled in debugging mode.
Open (Alt-O, editing only)
This opens the file if it exists, or opens a new editing buffer
with the given filename if it does not. Only .java files
are supported at the moment.
Save and Compile (Alt C, editing only)
This command first saves the source code in the top window, then
runs javac
. If compilation fails a window will
appear listing the errors.
Save (Alt Shift S, editing only)
This saves the source code.
Save Backup (Alt S, editing only)
This is not the same as a normal "Save As". It saves the file
with a filename provided via a dialog, but it does not change
the name of the file currently being edited. It is intended
for users to use this menu item when they are about to modify
the .java file and wish to make a backup in case something goes
wrong with this modification.
Restore Backup (Alt R, editing only)
This loads a filename provided via a dialog into the source code
window. The code in the source code window at the time will
be lost unless it has been saved by using Save and Compile.
Close (Alt Q, editing only)
Close the currently selected file.
Mark File as Compiled (editing only)
This tells the debugger that although you have modified a file, and have
not saved it, it is to regard the file as unmodified and compiled.
This menu item should be used with extreme caution, but is sometimes
helpful.
Save and Compile All (Alt Shift C, editing only)
Save and compile all the files open, which are in the current directory, together.
Save All (editing only)
Saves all the source files.
Exit (Alt X, editing and debugging)
This exits the debugger. If the source code has changed since the
last save you will be asked whether you want to save it via the
usual Yes/No/Cancel dialog.
Edit Menu
Goto Line (Alt G, editing and debugging)
This produces a dialog in which the user may enter an integer.
The caret of the source code window will then move to the start of
that line. This is useful for finding lines flagged as erroneous
by javac.
Search (Alt F, editing and debugging)
This produces a dialog in which a string may be entered.
The caret of the source code window will then move to the first
occurrence of that string after the current caret position.
Search Again (Shift Alt F, editing and debugging)
The same as Search except that the last string entered in a
Search dialog is used, you are not prompted for a new string.
Debugging Menu
Debug (Alt D, editing only)
This start the debugger. If the code had been changed you will
be asked if you want to save and compile and will only be allowed
to start debugging if you do so.
Debug Method (Shift Alt D, editing only)
This allows the user to set the initial method.
Only the initial method and methods it calls and methods they call
and so on are logged and stepped through. This can be used
for debugging different threads of a multi-threaded program.
Move the caret to the first line of the initial method (i.e. the
line that will be executed first when the method is called - usually
the line directly after the method header), and then
select this menu item. If the caret is not on the first line
of a method the program will execute fully without interruption.
When the initial method feature is used, methods which execute
before the initial method (and those on other threads) all
execute at a speed fractionally below that of the normal
Kaffe interpreter. Logged methods execute somewhat slower than this.
Thus, when debugging a long running program
and wishing to debug only a method which is not called for some
time, this feature allows a great deal of time to be saved.
Execute (Alt E, editing only)
This runs the application without interruption, until it
terminates or the "Stop All Executing" menu item is selected.
You can run the program as many times as you like concurrently,
unlike with debugging where there can only be one debugging
session at any point in time. A separate stdin/stdout/stderr
console is created for each execution, and for any debugging
session.
Stop All Executing (Alt Shift E, editing only)
Kills all the processes started by Execute. It has no effect
on debugging sessions.
Edit Arguments (Alt A, editing only)
This produces a dialog which can be used to change the arguments
to be passed when Executing or Debugging.
Change Buffer Size (editing only)
This produces a dialog which can be used to change the buffer size.
Every time the debugger sees a new thread which is eligible for
debugging it attempts to create a buffer of this size.
If it fails, the thread is unlogged and runs normally.
Each buffer slot takes up 17 bytes of memory, and each
line of code uses up about 8 buffer slots.
The default value is 131,072 slots, which takes up about 2 Mb,
and can reverse on average 16,000 lines.
If you want to debug many threads, or you have little
memory, you may wish to reduce this value. If you have,
as many developers will, a large amount of memory, or
you are debugging a single-threaded program, you may
wish to increase it.
Only 128 threads can be debugged: any beyond this will simply
run normally without interruption.
Step Over Backwards (Alt 1, debugging only)
Step Backwards (Alt 2, debugging only)
As with the command line interface.
If you try to step back too far
a dialog will appear informing you that you cannot.
Step Forwards (Alt 3, debugging only)
Step Over Forwards (Alt 4, debugging only)
Breakpoint Forwards (Alt 5, debugging only)
Breakpoint Backwards (Alt 6, debugging only)
As with the command line interface.
Terminate (Alt 7, debugging only)
This exits debugging mode and returns you to editing mode,
terminating the program being debugged.
Thread Menu
The commands perform the usual debugging commands on all
threads simultaneously, with the exception of
"All Other Breakpoint Forwards", which issues a breakpoint
on all threads other than the one currently selected.
All commands are debugging mode only, and there are no
shortcut keys as these commands are rarely used.
There are instances where they are useful however.
In particular it may be quicker to step through all the threads
together than to manipulate each separately by switching
between them.
Breakpoint Menu
Breakpoints can also be toggled by holding down CTRL while clicking
the mouse on the line. You can set breakpoints while editing to
be used during debugging, but if at any point you alter the source
code all the breakpoints in the altered file are cleared.
Toggle Breakpoint (Alt 8, editing and debugging)
Toggles the breakpoint status of the line the caret is on.
Clear All Breakpoints in File (editing and debugging)
Clears all the breakpoints in the currently selected file.
Clear All Breakpoints (Alt Shift 8, editing and debugging)
Clears all the breakpoints in all the files.
Watches Menu
The watch window is the smaller window below the source code window.
Delete Selected Watches (Alt 9, editing and debugging)
The user may delete a single watch by clicking on the line in the
watch window which highlights it and then selecting this menu item.
It is also possible to select any subset of the watches,
and then remove all of those watches by choosing this menu item.
Insert Watch Field (Alt Shift 9, editing and debugging)
This inserts a blank field just above the currently selected row.
Delete All Watches (Alt 0, editing and debugging)
Self-explanatory.
Help Menu
Brief Documentation (Alt Shift H, editing and debugging)
Displays this page.
About Bdbj (Alt H, editing and debugging)
Gives the version number.
Advice on Threads
Do not try to execute the start method of a given thread twice,
you should step back to the creation of the relevant object, recreate it
and then execute the start method again.
If you are dealing with interacting threads, you have to manually take
threads back to synchronization points as necessary.
As mentioned above, if you wish to run many threads, you may need to
reduce the buffer size.
Special Watches
Certain strings (starting with a !) can be used as watch variables to obtain
information about what the debugger is doing.
Most Useful Special Watches
- !lbuffpush: total pushes to the logging buffer so far in session (useful in choosing
a buffer size: you run the program, inspect this value and !pcbuffpush at the end, and set the buffer
size to the maximum of the two).
- !pcbuffpush: total pushes to the program counter buffer, see !lbuffpush.
- !line: current line of source code.
- !locals: total number of local variables (this and the next are useful when you
do not have a local variable table).
- !locali n: give local variable n treated as an integer (replace the i with f for floats,
d for doubles, l for longs, c for chars, and x to get the value in hexadecimal).
Less Useful Special Watches
- !pc: current program counter value.
- !sp: current depth of operand stack.
- !lbuffp: logging buffer position.
- !lbuffv: furthest back you can read on logging buffer.
- !pcbuffp: program counter buffer position.
- !pcbuffv: furthest back you can read on program counter buffer.