zhaoyu@home:~$

jvm字节码参考

我们使用javap将如下程序的class文件编译获得字节码。

package net.zhaoyu.javapros.test;
public class Test2 {
    public static void main(String[] args) {
        String str_a = "a";
        String str_b = "b";
        String str_ab = "a" + "b";
        String str_ab1=str_a+str_b;
        String str_ab2 = "ab";
        System.out.println(str_ab==str_ab1);
        System.out.println(str_ab==str_ab2);
        String str_new=new String("ab");
    }
}

得到的字节码分为多个部分,我主要关注常量池部分和代码指令部分。

Constant pool

字节码的常量池部分定义了class文件使用到的常量,如上程序的部分常量池定义如下:

   #1 = Methodref          #14.#27        // java/lang/Object."<init>":()V
   #2 = String             #28            // a
   #3 = String             #29            // b
   #4 = String             #30            // ab
   #5 = Class              #31            // java/lang/StringBuilder
   #6 = Methodref          #5.#27         // java/lang/StringBuilder."<init>":()V
   #7 = Methodref          #5.#32         // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   #8 = Methodref          #5.#33         // java/lang/StringBuilder.toString:()Ljava/lang/String;
   #9 = Fieldref           #34.#35        // java/lang/System.out:Ljava/io/PrintStream;
  #10 = Methodref          #36.#37        // java/io/PrintStream.println:(Z)V
  #11 = Class              #38            // java/lang/String
  #12 = Methodref          #11.#39        // java/lang/String."<init>":(Ljava/lang/String;)V
  #13 = Class              #40            // net/zhaoyu/javapros/test/Test2
  #14 = Class              #41            // java/lang/Object
  #15 = Utf8               <init>
  #16 = Utf8               ()V
  #17 = Utf8               Code
  #18 = Utf8               LineNumberTable
  #19 = Utf8               main
  #33 = NameAndType        #46:#47        // toString:()Ljava/lang/String;
  ......
  • CONSTANT_Class: 类或接口的符号引用。
  • CONSTANT_Fieldref: 字段的符号引用。
  • CONSTANT_Methodref: 方法的符号引用。
  • CONSTANT_InterfaceMethodref: 接口方法的符号引用。
  • CONSTANT_Integer: 整型常量。
  • CONSTANT_String: 字符串型常量。
  • CONSTANT_String: 字符串型常量。
  • CONSTANT_Float: 浮点型常量。
  • CONSTANT_Double: 双精度浮点型常量。
  • CONSTANT_NameAndType: 字段或方法的符号引用。
  • CONSTANT_utf8: utf8编码的字符串。
  • CONSTANT_MethodHandle: 表示方法句柄。
  • CONSTANT_MethodType: 表示方法类型。
  • CONSTANT_InvokeDynamic: 表示一个动态方法调用点。

字段描述符

  • B byte类型值。
  • C char类型值,使用UTF-16编码。
  • D double值
  • F float类型值。
  • I int类型值。
  • J long类型值
  • LClassName; 类名为ClassName的一个实例。
  • S short类型值。
  • Z boolean类型值。
  • [ 表示一个数组。

方法描述符

例如:

Object m(int i,double d,Thread t){...}

字节码中描述为:

(IDLjava/lang/Thread;)Ljava.lang.Object;

方法字节码

上述程序的方法字节码描述如下:

public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=7, args_size=1  //stack表示操作栈的大小为2,locals表示本地变量表中有7个变量。args_size参数大小
         0: ldc           #2                  // String a //-将常量值从常量池中推送到栈顶。
         2: astore_1                            //-将栈顶的引用类型从栈中移出,存储到本地变量表。
         3: ldc           #3                  // String b 
         5: astore_2
         6: ldc           #4                  // String ab
         8: astore_3
         9: new           #5                  // class java/lang/StringBuilder //-创建一个对象,并将其引用值压入栈顶
        12: dup                                 //-复制栈顶元素,new后需要复制供invokesepcial使用。
        13: invokespecial #6                  // Method java/lang/StringBuilder."<init>":()V  //-构造方法的调用
        16: aload_1                             //-本地变量表1位置的对象入栈顶。
        17: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        20: aload_2                             //-本地变量表2位置的对象入栈顶。
        21: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        24: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        27: astore        4                     //-将栈顶元素的值到变量表位置4.
        29: ldc           #4                  // String ab
        31: astore        5
        33: getstatic     #9                  // Field java/lang/System.out:Ljava/io/PrintStream;
        36: aload_3
        37: aload         4
        39: if_acmpne     46
        42: iconst_1
        43: goto          47
        46: iconst_0
        47: invokevirtual #10                 // Method java/io/PrintStream.println:(Z)V
        50: getstatic     #9                  // Field java/lang/System.out:Ljava/io/PrintStream;
        53: aload_3
        54: aload         5
        56: if_acmpne     63
        59: iconst_1
        60: goto          64
        63: iconst_0
        64: invokevirtual #10                 // Method java/io/PrintStream.println:(Z)V
        67: new           #11                 // class java/lang/String
        70: dup
        71: ldc           #4                  // String ab
        73: invokespecial #12                 // Method java/lang/String."<init>":(Ljava/lang/String;)V
        76: astore        6
        78: return
      LineNumberTable:
        line 5: 0
        line 6: 3
        line 7: 6
        line 8: 9
        line 9: 29
        line 10: 33
        line 11: 50
        line 12: 67
        line 13: 78
    ......

指令说明