java栈映射表

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------|------------|   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值