Martoon
Martoon

Reputation: 390

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?

Upvotes: 3

Views: 139

Answers (2)

dejvuth
dejvuth

Reputation: 7146

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.
  • ...

Upvotes: 4

Antimony
Antimony

Reputation: 39451

Yes. Bytecode verification enforces that the stack size is constant at any given instruction, regardless of control flow. (It also enforces that the types are compatible). Therefore, this is true not only of bytecode derived from compiled Java, but any valid bytecode at all.

Upvotes: 3

Related Questions