介绍
操作数栈也称表达式栈
在方法执行过程中,根据字节码指令,往栈里写入数据或提取数据,即入栈/出栈。
- 某些字节码指令把值压入操作数栈,其余指令将操作数取出栈。使用他们后再把结果压入栈。
- 比如:执行复制、交换、求和等操作。
操作数栈主要用于保存计算过程的中间结果,同时作为计算过程中临时的存储空间。
操作数栈是JVM执行引擎的一个工作区,当一个方法刚开始执行得时候,一个新的栈帧也会随之被创建出来,其操作数栈是空的。
每一个操作数栈都会有一个明确的栈深度用于存储数值,最大深度在编译器就定义好了,保存在方法的code属性中,即max_stack值。
栈中的元素类型和占位和局部变量表类似。
注意:
操作数栈并非采用访问索引的方式访问数据,而只能通过栈的操作。
如果被调用的方法带有返回值,返回值也会被压入当前栈帧的操作数栈中,并更新pc寄存器中下一条需要执行的字节码指令。
操作数栈中的元素类型必须与字节码指令的序列严格匹配–>由编译器在编译期间验证,同时在类加载过程中的类检验阶段的数据流分析阶段要再次验证。
举例说明
不知道大家有没有疑惑过,操作指令中,一个push和一个store指令才是一个完整的赋值操作,那么当push发生时,数据究竟存放在哪里?
肯定不是局部变量表,因为当且仅当store操作指令完成后,局部变量表中的对应slot才会有值。肯定有一个临时存放空间来保存这些中间运算结果。这个空间就是操作数栈。
操作数栈的作用在加法(二元操作)操作中得以完整体现,比如:现在有a,b两变量存放在局部变量表中。想要进行加法,必须先从局部变量表中获取这两个值,如果没有临时空间,获取第二个值时,第一个值已经丢失了,就无法进行加法动作了。