Bdbj (version 1.2 beta, May 2002)

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.

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).

In order to open a class file, so that you can step through the bytecode, add an item in the file list of the form: java/io/RandomAccessFile.class. It is not necessary for this to correspond to anything in your directory structure, only that this class is reachable from the classpath.

Environment Variables

Usually, you should not need to alter these, by you may wish to.

Disclaimer and Licensing

Bdbj is still under development and we can accept no responsibility for averse consequences arising from any aspect of its use.

Kaffe is covered by a GPL, see the file license.terms in the Kaffe source directory. This license extends to all the modified Kaffe code and all the Java code in the bdbj distribution.

Command Line Instructions

When invoking bdbjtty, a class name and optionally files are specified on the command line. You have the option of altering these before starting debugging. bdbjtty starts up in the Setup mode with the following commands available: Having entered the command "start" you are transferred to the Debugging mode and may use the following commands: There are a number of ways in which the debugger will reply:

The Graphical Interface

The top half of the screen shows the source code. Below this is the status bar, and below this, 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 there is a source file chooser and to the bottom left there 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 not to compile without saving. 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. When stepping through bytecode, the current line of execution is highlighted in yellow. 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.

Breakpoints can be set by right clicking on a line while holding down the CTRL key.

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.

Open Bytecode (editing only)

Typing a classname such as java/io/RandomAccessFile, causes the class file to be disassembled and placed in a file window. The bytecode can be stepped through, and breakpoints set in it. When a successful compilation occurs, all open bytecode files are re-disassembled.

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

Undo (Ctrl Z, editing and debugging)

Undo the last edit.

Redo (Ctrl Y, editing and debugging)

Redo an edit which has been undone.

Cut (Ctrl X, editing and debugging)

Delete the selected text, copying it to the clipboard.

Copy (Ctrl C, editing and debugging)

Copy the selected text to the clipboard.

Paste (Ctrl V, editing and debugging)

Insert the clipboard contents at the current location.

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 any line in the initial method (but it must be a line which has a corresponding bytecode instruction; variable declarations without assignment do not), and then select this menu item. If the caret is not on an appropriate line then 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) 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.

Run Debug Script (editing only)

Selecting this menu item will start a debugging session, where settings such as the buffer size or deep logging list are taken from a file, rather than those entered in the dialog boxes. If the currently selected file has a name which ends with ".bdbj", then this is used. If not, the first open file found with such an ending is used. The commands in the file are passed directly to the debugger and have the same form as the command line interface commands, e.g. "deeplog java.io.*". It is recommended that the only commands placed in such a file are: deeplog, arg, args, init and buffer. If a "start" command is used, then commands such as "step" can follow it, however the debugger can behave in unexpected ways if you do this, especially if your program is multi-threaded.

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. The arguments should be entered in the table, one per line. Do not enter the arguments on the first line separated by spaces as this will probably not work as intended. "More" adds a new field at the bottom of the table. "Insert" inserts a field just above the currently selected field. "Delete" deletes all currently selected fields.

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.

Edit Deep Logging List (editing only)

The deep logging list is a list of class names or partial class names (ending in a star) which are to be deep logged. For example: "ed.* java.io.Input* java.util.*". The only wildcard that is allowed is a star and it can only occur at the end. Classes in this list will be logged, but you cannot step through them. To debug a large project, you can open the main class, set deep logging to your root package name, and then open whatever classes you wish to step through. Then, your whole project is logged, and you can step through whichever parts you wish. You must add java.io.* to this list if you want basic file I/O to be reversed.

Show Command Console (debugging only)

This opens a window which shows the debugger's internal messages. Messages sent from the user interface begin with a "+", and replies begin with a "-". You can enter commands into the console to be sent (do not use a "+"). It is not advised to toggle breakpoints in this way, and with the GUI in the same debugging session.

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.

Garbage Collect Buffer (debugging only)

This prevents stepping back from the currently reached point, but allows all objects that are in the logging buffer to be garbage collected. A more natural solution to the sort of problem that would lead you to want to do this is to reduce the buffer size.

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.

Bytecode Menu

These commands allow you to step through the bytecode rather than the source code. They can be issued even when the bytecode is not open (the current line indicated just moves when you enter a new line). The bytecode breakpoints are separate from source code breakpoints. Use the breakpoint menu items of this menu when and only when you want to run to the next bytecode breakpoint. This separation is for efficiency reasons.

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, or to debug at the bytecode level.

Most Useful Special Watches

Less Useful Special Watches