java - JVM:编译器需要在方法字节码的哪些位置指定堆栈映射帧?

标签 java jvm bytecode java-bytecode-asm

这是 asm 用户指南的摘录:

In order to save space, a compiled method does not contain one frame per instruction: in fact it contains only the frames for the instructions that correspond to jump targets or exception handlers, or that follow unconditional jump instructions. Indeed the other frames can be easily and quickly inferred from these ones.

我能理解为什么 jvm 在跳转目标和异常处理程序中需要堆栈映射帧,但是在 goto 之后不需要堆栈映射帧是不必要的要求,因为必须是方法字节码中某处的跳转指令,它指向 goto 指令之后的指令,这种情况将由第一个要求处理。它必须是那样,否则 goto 之后的指令将无法访问,因此可以丢弃。

例子:

方法及其字节码如下:

public class t {
    public static void main(String[] s) {
        int i = 10;
        while ( i > 0 ) {
            i = i + 1;
        }
        int j = 10;
    }
}



  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=1
         0: bipush        10
         2: istore_1
         3: iload_1
         4: ifle          14
         7: iload_1
         8: iconst_1
         9: iadd
        10: istore_1
        11: goto          3
        14: bipush        10
        16: istore_2
        17: return
      LineNumberTable:
        line 9: 0
        line 10: 3
        line 11: 7
        line 13: 14
        line 14: 17
      StackMapTable: number_of_entries = 2
        frame_type = 252 /* append */
          offset_delta = 3
          locals = [ int ]
        frame_type = 10 /* same */
}

索引 11 处的指令是 goto 指令,索引 4 处的指令有 14,紧接在 11< 之后的指令 因为它是跳转目标。

在无条件跳转之后要求堆栈映射框架背后的合理性是什么?

最佳答案

堆栈映射的目标是允许在代码的单次线性传递中执行验证。

如果goto后面的代码没有指向它的跳转,那么代码就死了,理论上不需要验证。然而,验证者并不知道这一点。由于它是对代码执行单遍,因此无法提前知道代码是否已死。因此,它必须验证所有内容,这意味着它需要一个堆栈框架作为开始。

请注意,这与传统的非堆栈映射 validator 不同。在引入堆栈映射之前, validator 将简单地迭代它找到的所有代码,(有效地)跟随跳跃,并迭代直到收敛。这意味着在旧 validator 下,死代码根本不会被触及。

关于java - JVM:编译器需要在方法字节码的哪些位置指定堆栈映射帧?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50781057/

相关文章:

.net - 是否有任何IL编辑器来更改程序集的字节码?

java - 如何处理过时的元素引用: element is not attached to the page document

java - 为什么 JVM 的实际内存占用比我的 Xmx 大这么多?

java - 如何确保 JVM 以 Xms 的值启动

java - Java非堆内存和栈内存有什么区别?如果不是,它们是否相同?它们之间有什么区别?

mysql - Windows 上不可读的字节码数据库 tar.gz (Maxmind)

java - 我如何知道在字节码级别引发的异常的类型?

java - Spring Batch - 为什么作业步骤 bean 是在 Web 上下文而不是作业上下文中创建/执行的?

java - 为 SimpleEntry 添加 Comparable 接口(interface)

Java 获取查询字符串