首先来看一下源代码:
public class OperandStackTest {
public static void main(String[] args) {
OperandStackTest test = new OperandStackTest();
System.out.println(test.calc()); // 90000
}
public int calc(){
int a = 100;
int b = 200;
int c = 300;
return (a+b)*c;
}
}
反编译后的字节码文件
代码追踪流程:
第一步:
首先执行偏移地址为0的指令,Bipush指令的作用是将单字节的整形常量值(-127~128)推入操作数栈顶,跟随有一个参数,指明推送的常量值为100。如图所示:
第二步:
执行偏移地址为2的指令,istore_1指令的作用是操作数栈顶的整形值出栈并存放到第一个局部变量槽中,后续4条指令(一直到偏移地址为11的指令为止)都是做的一样的事情,也就是在对应的代码中把变量a,b,c赋值100,200,300。
第三步:
执行偏移地址为11的指令,iload_1指令的作用是将局部变量表的第一个变量槽的整形值复制到操作数栈顶。
第四步:
执行偏移地址为12的指令,iload_2指令的作用与iload_1类似,把第二个变量槽的整形值入栈。
第五步:
执行偏移地址为13的指令,iadd指令的作用是将操作数栈顶的头两个栈顶元素出栈,做整形加法,然后把结果入栈,在iadd指令执行完毕,栈中的原有的100,200被出栈,它们的和和300被从新入栈。
第六步:
执行偏移地址为14的指令,iload_3指令把存放在第三个局部变量槽中的300入栈到操作数栈,这时操作数栈的值为两个整形数字300,下一条指令imul将操作数栈顶的两个元素出栈,做整形乘法,然后把结果入栈,与iadd指令的执行过程类似。
第七步:
执行偏移地址为16的指令,ireturn指令是方法返回指令之一,它将结束方法执行并将操作数栈顶的整形值返回给该方法的调用者,整个过程执行结束。