Search code examples
javabytecodejvm-bytecode

Can operand stack size differ at given instruction depending on execution history?


For example, for method

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

javac generates the following bytecode:

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

At label 4 stack has same size (0), no matter which instruction was previous: 3 or 16.

Is that generally true for bytecode generated from java code?


Solution

  • For a reference to the Antimony's answer, see the JVM specification §4.9.2. Structural Constraints (thank you Holger!):

    • ...
    • If an instruction can be executed along several different execution paths, the operand stack must have the same depth (§2.6.2) prior to the execution of the instruction, regardless of the path taken.

    In the first version of this answer, I cited §4.10.2.1. The Process of Verification by Type Inference, which is for class files that do not contain StackMapTable attributes (version number of 49.0 or below):

    ... The verifier ensures that at any given point in the program, no matter what code path is taken to reach that point, all of the following are true:

    • The operand stack is always the same size and contains the same types of values.
    • ...