Java 什么是操作数堆栈?
我正在阅读有关JVM体系结构的文章。今天我读了关于操作数堆栈的概念。根据一篇文章: 操作数堆栈在字节码指令执行期间使用 与通用寄存器在本机CPU中的使用方式类似Java 什么是操作数堆栈?,java,jvm,Java,Jvm,我正在阅读有关JVM体系结构的文章。今天我读了关于操作数堆栈的概念。根据一篇文章: 操作数堆栈在字节码指令执行期间使用 与通用寄存器在本机CPU中的使用方式类似 我不明白:操作数堆栈到底是什么,它在jvm中是如何工作的?操作数堆栈保存着运算符执行操作时使用的操作数。操作数堆栈上的每个条目都可以保存任何Java虚拟机类型的值 从 Java虚拟机指令从操作数中获取操作数 堆栈,对其进行操作,并将结果推回操作数 堆栈操作数堆栈还用于准备要执行的参数 传递给方法并接收方法结果 例如,指令将添加两个整数值
我不明白:操作数堆栈到底是什么,它在jvm中是如何工作的?操作数堆栈保存着运算符执行操作时使用的操作数。操作数堆栈上的每个条目都可以保存任何Java虚拟机类型的值 从 Java虚拟机指令从操作数中获取操作数 堆栈,对其进行操作,并将结果推回操作数 堆栈操作数堆栈还用于准备要执行的参数 传递给方法并接收方法结果 例如,指令将添加两个整数值,所以它将从操作数堆栈中弹出最上面的两个整数值,并在添加后将结果推入操作数堆栈 有关更详细的参考资料,您可以查看 在操作数堆栈的上下文中对其进行汇总
_______________________________
| _____________________ |
| | + --------+ | |
| JVM | | Operand | | |
| Stack | FRAME | Stack | | |
| | +---------+ | |
| |_____________________| |
|_______________________________|
- JVM支持多线程执行环境。每根线 执行在创建线程的同时创建其私有java虚拟机堆栈(JVM堆栈)
- 这个Java虚拟机堆栈存储帧。框架保存数据、部分结果、方法返回值并执行动态链接
- 每个帧包含堆栈,称为操作数堆栈,它保存JVM类型的操作数值。操作数堆栈的深度在编译时确定,并用运算符更新
例如,考虑<代码> IADAD操作,将两个<代码> int <代码> s添加在一起。要使用它,请在堆栈上推送两个值,然后使用它:
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
现在,堆栈上的顶部值是将这三个局部变量相加的结果
让我们更详细地看一下第二个示例:
我们假设:
- 堆栈一开始是空的(这几乎从来都不是真的,但在开始之前我们不在乎上面有什么)
- 局部变量0包含
27
- 局部变量1包含
10
- 局部变量2包含
5
10
和27
从堆栈中“弹出”,将它们相加,并推送结果(37
)。现在我们有:
+−−−−−−−+
| stack |
+−−−−−−−+
| 37 |
+−−−−−−−+
这给了我们:
+−−−−−−−+
| stack |
+−−−−−−−+
| 42 |
+−−−−−−−+
+−−−−−−−+
|堆叠|
+−−−−−−−+
| 42 |
+−−−−−−−+
(当然,这是最重要的。)
但我们不能确切地理解它是什么,以及它在jvm中是如何工作的
JVM定义了虚拟计算机,该计算机的指令集是基于堆栈的。这意味着JVM指令集中的指令通常会从堆栈中推送和弹出操作数。那么比如说,
- load指令可以从局部变量、实例变量或类变量中获取值,并将其推送到操作数堆栈上
- 算术指令将从操作数堆栈弹出值,执行计算并将结果推回堆栈,然后
- 存储指令将从堆栈中弹出一个值并存储它
- 在解释的情况下,操作数堆栈可能是由解释程序代码管理的数组。push和pop微操作的实现方式如下:
及stack[top++] = value;
- 当代码被JIT编译时,字节码指令序列被转换成本机指令序列,实现与字节码相同的功能。操作数堆栈位置映射到本机寄存器或内存位置;e、 g.在当前本机堆栈帧中。映射涉及各种优化,旨在优先使用寄存器(快)而不是内存(慢) 因此,在JIT编译的情况下,操作数堆栈不再具有明确的物理存在性,但编译程序的整体行为与操作数堆栈确实存在的情况相同1
1-实际上,考虑Java内存模型时,它可能并不完全相同。然而,记忆模型明确了差异的界限。在单线程计算不与外部交互的情况下(如I/O、时钟等),不可能有明显的差异。+1供《搭便车者宇宙指南》参考。你让我很开心哈哈哈我可以问一下CPU级操作数堆栈是如何工作的吗?我搞不清他们之间的关系。感觉只有一个或另一个应该做这项工作(即:执行指令):)。如果可能的话,你能简单地解释一下中间的流程吗?@stdout-Java虚拟机与CPU非常相似,这是有意的。一旦HotSpot对字节码进行了最小的首次通过优化,上面的堆栈很可能就是CPU堆栈(我还没有进入VM优化)。事实上,
iadd
很可能成为CPU的ADD
或ADC
(带进位添加)操作或类似操作。
iadd # Pops those off the stack, adds them, and pushes the result
+−−−−−−−+
| stack |
+−−−−−−−+
| 37 |
+−−−−−−−+
iload_2 # Push the value from local variable 2 onto the stack
+−−−−−−−+
| stack |
+−−−−−−−+
| 5 |
| 37 |
+−−−−−−−+
iadd # Pops those off the stack, adds them, and pushes the result
+−−−−−−−+
| stack |
+−−−−−−−+
| 42 |
+−−−−−−−+
stack[top++] = value;
value = stack[--top];