Java provides a handy tool javap
that prints the contents of a .class
file.
When used with the -v
flag, it shows the Java bytecode instructions in each method.
For the jvm
project, it can be run using javap -cp tests -v TEST_NAME
.
For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ javap -cp tests -v OnePlusTwo
public class OnePlusTwo
minor version: 3
major version: 45
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #6 // OnePlusTwo
super_class: #9 // java/lang/Object
interfaces: 0, fields: 0, methods: 1, attributes: 1
Constant pool:
#1 = Utf8 java/lang/Object
#2 = Utf8 SourceFile
#3 = Utf8 OnePlusTwo
#4 = Utf8 main
#5 = Utf8 Code
#6 = Class #3 // OnePlusTwo
#7 = Utf8 ([Ljava/lang/String;)V
#8 = Utf8 OnePlusTwo.j
#9 = Class #1 // java/lang/Object
{
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=5, locals=1, args_size=1
0: bipush 1
2: bipush 2
4: iadd
5: return
}
SourceFile: "OnePlusTwo.j"
Note that much of this information is extraneous: mainly the Constant pool
and Code
sections will be useful!
The number to the left of each instruction indicates its offset in the bytecode (so you can see that bipush
is a 2-byte instruction).
The instructions are listed using the same mnemonics as in the spec.
Any arguments to the instruction (e.g. 1
or 2
above) are listed after the instruction mnemonic.
Here is a longer method (Jumps.catalan()
) that shows a few more instructions:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public static int catalan(int);
descriptor: (I)I
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=3, args_size=1
0: iload_0
1: ifne 6
4: iconst_1
5: ireturn
6: iconst_0
7: istore_1
8: iconst_0
9: istore_2
10: iload_1
11: iload_2
12: iinc 2, 1
15: invokestatic #7 // Method catalan:(I)I
18: iinc 0, -1
21: iload_0
22: invokestatic #7 // Method catalan:(I)I
25: imul
26: iadd
27: istore_1
28: iload_0
29: ifgt 10
32: iload_1
33: ireturn
Note that the jump instructions are shown with absolute offsets.
For example, ifgt 10
means “jump to instruction 10 if the value popped from the stack is greater than 0”.