3

例如,对于方法

public int f() {
    int k = 1;
    for (int i = 0; i < 10; i++) {
        k += 2;
    }
    return k;
}

javac生成以下字节码:

public int f();
Code:
   0: iconst_1
   1: istore_1
   2: iconst_0
   3: istore_2
   4: iload_2
   5: bipush        10
   7: if_icmpge     19
  10: iinc          1, 2
  13: iinc          2, 1
  16: goto          4
  19: iload_1
  20: ireturn

在标签 4 处,堆栈具有相同的大小 (0),无论之前是哪条指令:3 或 16。

对于从 java 代码生成的字节码,这通常是正确的吗?

4

2 回答 2

4

有关 Antimony 答案的参考,请参阅 JVM 规范 §4.9.2。结构约束(谢谢 Holger!):

  • ...
  • 如果一条指令可以沿多个不同的执行路径执行,则操作数堆栈在指令执行之前必须具有相同的深度(第 2.6.2 节),而不管采用的路径如何。

在这个答案的第一个版本中,我引用了§4.10.2.1。类型推断验证过程,适用于不包含StackMapTable属性的类文件(版本号为49.0或以下):

...验证器确保在程序中的任何给定点,无论采用什么代码路径到达该点,以下所有内容都是正确的:

  • 操作数堆栈始终具有相同的大小并包含相同类型的值。
  • ...
于 2016-04-26T08:30:11.320 回答
3

是的。字节码验证强制堆栈大小在任何给定指令处都是恒定的,而与控制流无关。(它还强制类型兼容)。因此,这不仅适用于从编译的 Java 派生的字节码,而且适用于任何有效的字节码。

于 2016-04-26T02:47:14.457 回答