聊聊栈帧中的局部变量表和操作数栈
前置阅读【图解JVM内存模型及JAVA程序运行原理】:https://developer.aliyun.com/article/1218034?utm_content=g_1000372435
本文内容和【图解JVM内存模型及JAVA程序运行原理】一文中的“程序样例执行详解”相关。
代码示例:
public int operandStackExample(int a, int b) { int c = a * b; int d = a + b; return c - d; }
- 操作数栈执行过程:
- 将参数 a 压入操作数栈中,操作数栈:[a]。
- 将参数 b 压入操作数栈中,操作数栈:[a, b]。
- 执行乘法操作,弹出操作数栈顶的两个元素 a 和 b,计算 a * b 的结果 c,将结果 c 压入操作数栈中,操作数栈:[c]。
- 将参数 a 压入操作数栈中,操作数栈:[c, a]。
- 将参数 b 压入操作数栈中,操作数栈:[c, a, b]。
- 执行加法操作,弹出操作数栈顶的两个元素 a 和 b,计算 a + b 的结果 d,将结果 d 压入操作数栈中,操作数栈:[c, d]。
- 执行减法操作,弹出操作数栈顶的两个元素 c 和 d,计算 c - d 的结果,将结果压入操作数栈中,操作数栈:[c-d]。
- 将操作数栈顶的值返回给方法调用者。
总结:在这个例子中,操作数栈的完整执行过程包括将参数和临时数据压入栈中,执行计算操作,弹出栈顶元素,将计算结果压入栈中,最终将栈顶元素返回给方法调用者。
- 局部变量表执行过程:
- 方法开始执行时,创建局部变量表,分配足够的空间存储局部变量。在这个例子中,局部变量表有 4 个槽,分别存储参数 a、参数 b、局部变量 c 和局部变量 d。
- 将参数 a 的值存入局部变量表的第 0 个槽中。
- 将参数 b 的值存入局部变量表的第 1 个槽中。
- 计算
a * b
的结果,并将结果存入局部变量表的第 2 个槽(局部变量 c)。 - 计算
a + b
的结果,并将结果存入局部变量表的第 3 个槽(局部变量 d)。 - 从局部变量表中取出 c 和 d 的值,计算
c - d
的结果,并将结果压入操作数栈中。 - 将操作数栈顶的值返回给方法调用者。
总结:在这个例子中,局部变量表的完整执行过程包括创建局部变量表,将参数和局部变量存入表中,读取表中的值进行计算,最终将计算结果压入操作数栈中。
- 总结:
局部变量表和操作数栈在 JVM 中分别有不同的作用:
-
局部变量表:局部变量表用于存储方法的参数和局部变量,包括基本数据类型和对象引用。它的作用是提供一个临时的存储区域,用于在方法执行过程中存储和访问方法的参数和局部变量。
-
操作数栈:操作数栈用于存储方法执行过程中的临时数据,包括基本数据类型和对象引用。它的作用是提供一个临时的存储区域,用于在方法执行过程中进行计算和操作。
因为局部变量表和操作数栈在结构和用途上有明显的区别,所以不能用局部变量表替代操作数栈。局部变量表主要用于存储方法的参数和局部变量,而操作数栈主要用于存储方法执行过程中的临时数据。如果将操作数栈的功能转移到局部变量表中,会导致局部变量表的使用变得复杂,而且会增加 JVM 的实现难度。因此,在 JVM 中,局部变量表和操作数栈都是必不可少的。