JBCD Crash Course

What is JBCD

JBCD (the Java Bytecode Debugger) is an interactive debugger for Java bytecode. It allows a programmer to step through bytecode one statement at time. The tool is indended for people who are writing programs to generate or modify bytecode. JBCD can be used with any Java compiler.

Running a program

In this example, we will debug the Hello World program:
  public class HelloWorld {
    public static void main (String args []) {
      System.out.println("Hello world");
    }
  } 
The method compiles into this bytecode:
  0:    getstatic		java.lang.System.out Ljava/io/PrintStream; (2)
  3:    ldc		"Hello world" (3)
  5:    invokevirtual	java.io.PrintStream.println (Ljava/lang/String;)V (4)
  8:    return
Normally the program is started by executing
% java HelloWorld
You can debug your program with JBCD by invoking jbcd, and passing your normal command line as a command line argument as in
% java jbcd HelloWorld
When JBCD starts up, it prints the first instruction of the program, and waits for input:
% java jbcd Hello
0:    getstatic		java.lang.System.out Ljava/io/PrintStream; (2)
jbcd> _

Stepping through code

You can use the step command to step through bytecode one statement at a time. The current instruction is printed after each step. If a method is invoked, the debugger will step into that method. The next command that steps over method invokations has not yet been implemented.

Use the cont command to continue program execution to the next breakpoint.

% java jbcd Hello
0:    getstatic		java.lang.System.out Ljava/io/PrintStream; (2)
jbcd> step
3:    ldc		"Hello world" (3)
jbcd> step
5:    invokevirtual	java.io.PrintStream.println (Ljava/lang/String;)V (4)
jbcd> cont
Hello world
% _

Seeing where you are

JBCD prints out each instruction as you step through code. If you would like to see more of the code in the current method, use the list command. This will print the 10 statements around the current instruction.
% java jbcd Hello
0:    getstatic		java.lang.System.out Ljava/io/PrintStream; (2)
jbcd> list
0:    getstatic		java.lang.System.out Ljava/io/PrintStream; (2)
3:    ldc		"Hello world" (3)
5:    invokevirtual	java.io.PrintStream.println (Ljava/lang/String;)V (4)
8:    return

jbcd> _

Setting breakpoints

Breakpoints are set with "break aClass.aMethod(args):index" or "break aMethod(args):index". If no class name is given, the current class is assumed. The index is optional. If omitted the breakpoint is placed at the first instruction in the method. You can see a list of active breakpoints by executing break with no arguments.

Breakpoints are cleared with the clear command. With no arguments, clear removes all breakpoints. Clear can also be given a list of integer arguments, cooresponding to the ids of breakpoints to remove. Breakpoint ids are printed when the breakpoints are listed by break.

% java jbcd Hello
0:    getstatic		java.lang.System.out Ljava/io/PrintStream; (2)
jbcd> break main(java.lang.String[]):5
jbcd> break
[0] Breakpoint: Hello.main(java.lang.String[]):5
jbcd> cont
5:    invokevirtual	java.io.PrintStream.println (Ljava/lang/String;)V (4)
jbcd> clear 0
jbcd> break
No breakpoints set
jbcd> _