贪婪算法  • • •  反最佳实践       all posts in Archive

Java Bytecode

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
}