java栈映射表

来源:互联网 发布:w3school sql 编辑:程序博客网 时间:2024/06/06 23:16

java栈映射表(StackMapTable)

源码

  public String hello(String content) throws RemoteException {        int i= 10;        if (i==10) {            System.out.println("10");        }else {            System.out.println(i);        }       if(content == null) {            return "null is not allowed";        }        if (content.equals("hello")) {            return "how are you?";        }        if (content.equals("bye")) {            return "bye bye!";        }        return "This is your input :"+content;    }

反编译

javap -c -v -cp bin .\bin\com\ymx\rmi\service\TestServiceImpl.class
部分结果如下:

  public java.lang.String hello(java.lang.String) throws java.rmi.RemoteException;    flags: ACC_PUBLIC    Code:      stack=2, locals=3, args_size=2         0: bipush        10         2: istore_2         3: iload_2         4: bipush        10         6: if_icmpne     20         9: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;        12: ldc           #3                  // String 10        14: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V        17: goto          27        20: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;        23: iload_2        24: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V        27: aload_1        28: ifnonnull     34        31: ldc           #6                  // String null is not allowed        33: areturn        34: aload_1        35: ldc           #7                  // String hello        37: invokevirtual #8                  // Method java/lang/String.equals:(Ljava/lang/Object;)Z        40: ifeq          46        43: ldc           #9                  // String how are you?        45: areturn        46: aload_1        47: ldc           #10                 // String bye        49: invokevirtual #8                  // Method java/lang/String.equals:(Ljava/lang/Object;)Z        52: ifeq          58        55: ldc           #11                 // String bye bye!        57: areturn        58: new           #12                 // class java/lang/StringBuilder        61: dup        62: invokespecial #13                 // Method java/lang/StringBuilder."<init>":()V        65: ldc           #14                 // String This is your input :        67: invokevirtual #15                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;        70: aload_1        71: invokevirtual #15                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;        74: invokevirtual #16                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;        77: areturn      LineNumberTable:        line 24: 0        line 25: 3        line 26: 9        line 28: 20        line 30: 27        line 31: 31        line 33: 34        line 34: 43        line 36: 46        line 37: 55        line 39: 58      StackMapTable: number_of_entries = 5           frame_type = 252 /* append */             offset_delta = 20        locals = [ int ]           frame_type = 6 /* same */           frame_type = 6 /* same */           frame_type = 11 /* same */           frame_type = 11 /* same */    Exceptions:      throws java.rmi.RemoteException

其中StackMapTable即为栈映射表。

意义

  1. 仅用于有跳转的字节指令中,如goto、ifeq、if_icmpne、ifnonnull等
  2. 跳转语句有块的概念。块的起点是跳转字节指令的目的地址,如第6条:
    指令:6: if_icmpne 20
    意义是,如果整数比较不相等,则跳转到第20条指令。20条为:
    指令:20: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
    所以,第一个frame_type的offset_delta是20,代表第一个块偏移量是20。
    第二个frame_type是6,代表第二块偏移量是6。
    以此类推,第三块偏移量6,第四块偏移量是11,第五块偏移量是11。
  3. 说明
    每个基本块是以栈映射帧的形式存在的。字节码偏移量,和栈映射帧的偏移量不是一样的,字节码偏移量+1=帧偏移量。
    第一个的frame_type是根据类的签名算出来的,如果frame_type和offset_delta一样,则不显示offset_delta
    因为可以计算出:
    第一块的字节码偏移量20,StackMapFrame偏移量21,结束是21+6-1=26。
    第二块的字节码偏移量21+6=27,StackMapFrame偏移量6,结束是27+6=33。
    第三块的字节码偏移量33+1=34,StackMapFrame偏移量11,结束是34+11=45。
    第四块的字节码偏移量45+1=46,StackMapFrame偏移量11,结束是46+11=57。
    第五块的字节码偏移量57+1=58。
  4. 图示
  0              20            27            34             46              58  |------20------|------6------|------6------|------11------| ------11------|------------|