What is Java Bytecode
Java bytecode is the instruction set of the Java virtual machine (JVM).
Thus, bytecode from architecture view is like a abstraction layer that separate linguistic programming and code excecution. That’s also the reason we can use other language to build JVM application: JRuby, Groovy, Scala, Clojure, Kotlin …
Usually, we don’t need check code in Bytecode, as it’s too unintelligibility, like reading assemble language, but at times in order to get clearer understanding how JVM works, we’d better know how to generate these bytecode files.
Sample Code
public class Test {
public static void main(String[] args) {
String name = "William";
System.out.println("Hello " + name);
}
}
Bytecode Outline
The best tool is Eclipse Plugin: Bytecode Outline. The superiority is displaying related bytecode line while you point to different line in source code.
The bytecode generated by it, looks like following:
// access flags 0x9
public static main([Ljava/lang/String;)V
L0
LINENUMBER 5 L0
LDC "William"
ASTORE 1
L1
LINENUMBER 6 L1
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
NEW java/lang/StringBuilder
DUP
LDC "Hello "
INVOKESPECIAL java/lang/StringBuilder.<init> (Ljava/lang/String;)V
ALOAD 1
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
L2
LINENUMBER 7 L2
RETURN
L3
LOCALVARIABLE args [Ljava/lang/String; L0 L3 0
LOCALVARIABLE name Ljava/lang/String; L1 L3 1
MAXSTACK = 4
MAXLOCALS = 2
Generate Bytecode by JDK tools
Ofcourse, we can view bytecode with troublesome way …
1. Generate Class file
first have to compile source code:
➜ $ javac Test.java
This will generate Test.class file, just that easy, but how to view it as bytecode ?
2. See content of Java Class file
We use GUI tool like JD-GUI. But if we were using MacOS or Unix, we can simply use HEXDUMP.
➜ $ hexdump -C Test.class
00000000 ca fe ba be 00 00 00 34 00 2a 0a 00 0b 00 14 08 |.......4.*......|
00000010 00 15 09 00 16 00 17 07 00 18 0a 00 04 00 14 08 |................|
00000020 00 19 0a 00 04 00 1a 0a 00 04 00 1b 0a 00 1c 00 |................|
00000030 1d 07 00 1e 07 00 1f 01 00 06 3c 69 6e 69 74 3e |..........<init>|
00000040 01 00 03 28 29 56 01 00 04 43 6f 64 65 01 00 0f |...()V...Code...|
00000050 4c 69 6e 65 4e 75 6d 62 65 72 54 61 62 6c 65 01 |LineNumberTable.|
00000060 00 04 6d 61 69 6e 01 00 16 28 5b 4c 6a 61 76 61 |..main...([Ljava|
00000070 2f 6c 61 6e 67 2f 53 74 72 69 6e 67 3b 29 56 01 |/lang/String;)V.|
00000080 00 0a 53 6f 75 72 63 65 46 69 6c 65 01 00 09 54 |..SourceFile...T|
00000090 65 73 74 2e 6a 61 76 61 0c 00 0c 00 0d 01 00 07 |est.java........|
000000a0 57 69 6c 6c 69 61 6d 07 00 20 0c 00 21 00 22 01 |William.. ..!.".|
000000b0 00 17 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 72 69 |..java/lang/Stri|
000000c0 6e 67 42 75 69 6c 64 65 72 01 00 06 48 65 6c 6c |ngBuilder...Hell|
000000d0 6f 20 0c 00 23 00 24 0c 00 25 00 26 07 00 27 0c |o ..#.$..%.&..'.|
000000e0 00 28 00 29 01 00 15 69 6f 2f 67 69 74 68 75 62 |.(.)...io/github|
000000f0 2f 76 69 6c 6c 69 6d 2f 54 65 73 74 01 00 10 6a |/villim/Test...j|
00000100 61 76 61 2f 6c 61 6e 67 2f 4f 62 6a 65 63 74 01 |ava/lang/Object.|
00000110 00 10 6a 61 76 61 2f 6c 61 6e 67 2f 53 79 73 74 |..java/lang/Syst|
00000120 65 6d 01 00 03 6f 75 74 01 00 15 4c 6a 61 76 61 |em...out...Ljava|
00000130 2f 69 6f 2f 50 72 69 6e 74 53 74 72 65 61 6d 3b |/io/PrintStream;|
00000140 01 00 06 61 70 70 65 6e 64 01 00 2d 28 4c 6a 61 |...append..-(Lja|
00000150 76 61 2f 6c 61 6e 67 2f 53 74 72 69 6e 67 3b 29 |va/lang/String;)|
00000160 4c 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 72 69 6e |Ljava/lang/Strin|
00000170 67 42 75 69 6c 64 65 72 3b 01 00 08 74 6f 53 74 |gBuilder;...toSt|
00000180 72 69 6e 67 01 00 14 28 29 4c 6a 61 76 61 2f 6c |ring...()Ljava/l|
00000190 61 6e 67 2f 53 74 72 69 6e 67 3b 01 00 13 6a 61 |ang/String;...ja|
000001a0 76 61 2f 69 6f 2f 50 72 69 6e 74 53 74 72 65 61 |va/io/PrintStrea|
000001b0 6d 01 00 07 70 72 69 6e 74 6c 6e 01 00 15 28 4c |m...println...(L|
000001c0 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 72 69 6e 67 |java/lang/String|
000001d0 3b 29 56 00 21 00 0a 00 0b 00 00 00 00 00 02 00 |;)V.!...........|
000001e0 01 00 0c 00 0d 00 01 00 0e 00 00 00 1d 00 01 00 |................|
000001f0 01 00 00 00 05 2a b7 00 01 b1 00 00 00 01 00 0f |.....*..........|
00000200 00 00 00 06 00 01 00 00 00 03 00 09 00 10 00 11 |................|
00000210 00 01 00 0e 00 00 00 3d 00 03 00 02 00 00 00 1d |.......=........|
00000220 12 02 4c b2 00 03 bb 00 04 59 b7 00 05 12 06 b6 |..L......Y......|
00000230 00 07 2b b6 00 07 b6 00 08 b6 00 09 b1 00 00 00 |..+.............|
00000240 01 00 0f 00 00 00 0e 00 03 00 00 00 05 00 03 00 |................|
00000250 06 00 1c 00 07 00 01 00 12 00 00 00 02 00 13 |...............|
0000025f
In this way, we just see it as source code, that’s not what we want.
3. Disassemble to Bytecode
We have to disassenble class file to bytecodes with javap :
- javap -c
Prints out disassembled code, that is, the instructions that comprise the Java bytecodes, for each of the methods in the class. These are documented in the Java Virtual Machine Specification.
➜ $ javap -c Test
Warning: Binary file Test contains io.github.villim.Test
Compiled from "Test.java"
public class io.github.villim.Test {
public io.github.villim.Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2 // String William
2: astore_1
3: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
6: new #4 // class java/lang/StringBuilder
9: dup
10: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
13: ldc #6 // String Hello
15: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
18: aload_1
19: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
22: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
25: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
28: return
}