我正在阅读有关JVM架构的内容。今天我读到了Operand Stack的概念。根据一篇文章:
在执行字节代码指令期间使用操作数堆栈 与通用寄存器在本机CPU中使用的方式类似。
我无法理解:操作数堆栈究竟是什么,它在jvm中是如何工作的?
答案 0 :(得分:56)
各种字节码操作如何获取输入,以及它们如何提供输出。
例如,考虑iadd
操作,它将两个int
加在一起。要使用它,您可以在堆栈上推送两个值,然后使用它:
iload_0 # Push the value from local variable 0 onto the stack
iload_1 # Push the value from local variable 1 onto the stack
iadd # Pops those off the stack, adds them, and pushes the result
现在堆栈的最高值是这两个局部变量的总和。下一个操作可能会占用顶部堆栈值并将其存储在某个位置,或者我们可能会在堆栈上推送另一个值来执行其他操作。
假设您要一起添加三个值。堆栈使这很容易:
iload_0 # Push the value from local variable 0 onto the stack
iload_1 # Push the value from local variable 1 onto the stack
iadd # Pops those off the stack, adds them, and pushes the result
iload_2 # Push the value from local variable 2 onto the stack
iadd # Pops those off the stack, adds them, and pushes the result
现在堆栈的最高值是将这三个局部变量加在一起的结果。
让我们更详细地看一下第二个例子:
我们假设:
27
10
5
所以最初:
+-------+ | stack | +-------+ +-------+
然后我们
iload_0 # Push the value from local variable 0 onto the stack
现在我们有了
+-------+ | stack | +-------+ | 27 | +-------+
下一步
iload_1 # Push the value from local variable 1 onto the stack
+-------+ | stack | +-------+ | 10 | | 27 | +-------+
现在我们进行补充:
iadd # Pops those off the stack, adds them, and pushes the result
它" pops"离开堆栈的10
和27
,将它们加在一起,然后推送结果(37
)。现在我们有:
+-------+ | stack | +-------+ | 37 | +-------+
第三次int
的时间:
iload_2 # Push the value from local variable 2 onto the stack
+-------+ | stack | +-------+ | 5 | | 37 | +-------+
我们做了第二个iadd
:
iadd # Pops those off the stack, adds them, and pushes the result
这给了我们:
+-------+ | stack | +-------+ | 42 | +-------+
(当然,这是Answer to the Ultimate Question of Life the Universe and Everything。)
答案 1 :(得分:13)
操作数堆栈保存运算符用于执行操作的操作数。操作数堆栈上的每个条目都可以包含任何Java虚拟机类型的值。
Java虚拟机指令从操作数中获取操作数 堆栈,对它们进行操作,并将结果推回操作数 堆。操作数堆栈也用于准备参数 传递给方法并接收方法结果。
例如,iadd
指令将添加两个整数值,因此它将从操作数堆栈中弹出前两个整数值,并在添加后将结果推入操作数堆栈。
有关详细信息,请查看JVMS#2.5 : Run-Time Data Areas
在操作数堆栈的上下文中总结它,
_______________________________
| _____________________ |
| | + --------+ | |
| JVM | | Operand | | |
| Stack | FRAME | Stack | | |
| | +---------+ | |
| |_____________________| |
|_______________________________|
答案 2 :(得分:6)
但难道不能确切地知道它是什么以及它在jvm中是如何工作的?
JVM定义虚拟计算机,该计算机的指令集基于堆栈。这意味着JVM指令集中的指令通常会从堆栈中推送和弹出操作数。例如,
@ T.J.Crowder的回答提供了一个更具体的例子。
如何实现操作数堆栈是特定于平台的,它取决于是否正在解释代码或是否已对其进行JIT编译。
在解释的情况下,操作数堆栈可能是由解释器代码管理的数组。推送和弹出微操作将实现如下:
stack[top++] = value;
和
value = stack[--top];
当代码被JIT编译时,字节码指令序列被转换为本机指令序列,实现与字节码相同的功能。操作数堆栈位置被映射到本机寄存器或存储器位置;例如在当前的本机堆栈框架中。映射涉及各种优化,旨在使用寄存器(快速)优先于内存(较慢)。
因此在JIT编译的情况下,操作数堆栈不再具有明确的物理存在,但编译程序的整体行为与操作数堆栈确实存在相同 1
1 - 实际上,考虑到Java内存模型时,它可能不完全相同。然而,存储器模型对差异可能存在明确的界限。对于不与外部交互的单线程计算(例如I / O,时钟等),可能没有可观察到的差异。