目录
前言
本篇将会讲述虚拟机栈中的另外一个组成部分: 操作数栈
什么是操作数栈
Java虚拟机的执行引擎被称为"基于栈的执行引擎",这其中的栈指的就是操作数栈,也可以称之为表达式栈,操作栈等
和局部变量表一样,操作数栈也是一个数组.但是和前者不同的是,操作数栈并非采用访问索引的方式来进行数据访问的,而是只能通过标准的入栈和出栈操作来完成一次数据访问.比如: 某一个指令将某个值压入到操作数栈中,稍后另外一个指令就可以弹出这个值来进行操作.操作数栈主要用于保存计算过程的中间结果,同时作为计算过程中变量临时的存储空间,操作数栈就是JVM执行引擎的一个工作区,当一个方法刚开始执行的时候,一个新的栈帧也会随之创建出来,这个方法的操作数栈是空的
特点
- 每一个操作数栈都会拥有一个明确的栈深度用于存储数值,其所需的最大深度在编译期间就定义好了,保存在方法的code属性中,为max_stack的值
- 栈中的任何一个元素都是可以任意的Java数据类型,32位的类型占用一个栈单位深度,64位的类型占用两个栈单位深度
- 操作数栈是虚拟机栈中栈帧的一个组成部分
实践
我们看一段伪代码,然后对代码进行编译,对编译后的信息进行分析
public class StackTest {
public static void main(String[] args) {
int o = 20;
int a = 10;
int b = o+a;
}
}
编译后
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
//操作数栈最大深度 //本地变量表最大深度
stack=2, locals=4, args_size=1
0: bipush 20 //压入操作数栈参数20
2: istore_1 //保出栈,保存本地变量表索引1位置
3: bipush 10 //压入操作数栈参数10
5: istore_2 //出栈,保存在本地变量表索引2位置
6: iload_1 //从本地变量表索引1取出参数,压入操作数栈
7: iload_2 //从本地变量表索引2取出参数,压入操作数栈
8: iadd //两个参数出栈,CPU运算后得到结果,压入操作数栈
9: istore_3 //出栈,保存计算结果到本地变量表索引3的位置
10: return //方法结束
LineNumberTable:
line 14: 0
line 15: 3
line 16: 6
line 17: 10
LocalVariableTable://本地变量表
Start Length Slot Name Signature
0 11 0 args [Ljava/lang/String;
3 8 1 o I
6 5 2 a I
10 1 3 b I
从我们编译之后得到的信息可以看到,在编译期间操作数栈的深度已经被确定了