Java jvm中pop指令和pop2指令的区别是什么?
我参考了下面的oracle jvm文档 pop操作弹出操作操作数堆栈的顶部值 格式 pop表格pop=87(0x57) 操作数堆栈…,值→ 说明从操作数堆栈中弹出顶部值 除非值是的值,否则不得使用pop指令 第1类计算类型(§2.11.1) pop2操作弹出顶部的一个或两个操作数堆栈值 格式 pop2表格pop2=88(0x58) 操作数堆栈格式1: …,值2,值1→ 其中,value1和value2均为类别1的值 计算类型(§2.11.1) 表格2: …,价值→ 其中,值是第2类计算类型的值(§2.11.1) 说明从操作数堆栈中弹出顶部的一个或两个值Java jvm中pop指令和pop2指令的区别是什么?,java,jvm,Java,Jvm,我参考了下面的oracle jvm文档 pop操作弹出操作操作数堆栈的顶部值 格式 pop表格pop=87(0x57) 操作数堆栈…,值→ 说明从操作数堆栈中弹出顶部值 除非值是的值,否则不得使用pop指令 第1类计算类型(§2.11.1) pop2操作弹出顶部的一个或两个操作数堆栈值 格式 pop2表格pop2=88(0x58) 操作数堆栈格式1: …,值2,值1→ 其中,value1和value2均为类别1的值 计算类型(§2.11.1) 表格2: …,价值→ 其中,值是第2类计算类
“从操作数堆栈中弹出顶部的一个或两个值”是什么意思?使用pop2时会有什么例子?编写一个小java程序,其中包含一个带有
System.currentTimeMillis();
不要使用此调用的结果。然后字节码看起来像
INVOKESTATIC java/lang/System.currentTimeMillis()J
POP2
System.currentTimeMillis()
在堆栈上放置一个长值(64位,宽)。但是,这个堆栈内容不再使用,因此必须弹出它,以便可以访问其他堆栈内容。32位(正常大小)需要一个简单的POP
,64位(宽大小)需要一个POP2
“从操作数堆栈中弹出顶部的一个或两个值”是什么意思
这样想吧1:
字节码会弹出一个值,该值占据堆栈上的一个32位字POP
字节码要么弹出一个占用两个x 32位字的值,要么弹出两个占用一个x 32位字的值POP2
POP2
时会有什么示例
long
或double
值;e、 g.丢弃方法调用产生的不需要的long
结果,或int
值javac
编译器不会向POP2发出POP2
值。如果堆栈上有两个32位值需要弹出,编译器将发出两条POP
指令。所以,对于普通Java代码,我不能给出案例2的例子。(但Java或其他语言的第三方编译器可能会使用它,或者人们用其他方式创建字节码。)
我对JVM内部的了解还不够清楚,但拥有POP2
的一个可能原因是,如果使用两条POP
指令来弹出(比如)一个long
,那么在序列的一部分,堆栈将处于无效状态。这可能导致验证错误
1-这不是严格正确的。堆栈上的值严格来说不是32或64位。例如,64位机器上的引用或返回地址是64位。。。但它仍然被建模为1类值。对此的解释是,字节码指令集最初设计用于在32位机器上进行解释。POP:从堆栈中弹出顶部的单个字项并将其丢弃 POP2:从堆栈中删除两个单字项(例如,两个整数,或一个整数和一个对象引用)或一个双字项(例如,双字或沿双字) 问题中提到的相同javadoc包含以下信息: 表2.3。Java虚拟机中的实际类型和计算类型 Actual type Computational type Category 1. byte int 1 2. char int 1 3. short int 1 4. int int 1 5. float float 1 6. reference reference 1 7. returnAddress returnAddress 1 8. boolean int 1 9. long long 2 10. double double 2 上述Java代码生成了以下字节码:
public static main(String[]) : void
L0
LINENUMBER 24 L0
INVOKESTATIC PopVsPop2.popint () : int
POP
L1
LINENUMBER 25 L1
INVOKESTATIC PopVsPop2.poplong () : long
POP2
L2
LINENUMBER 26 L2
INVOKESTATIC PopVsPop2.popLong () : Long
POP
L3
LINENUMBER 27 L3
RETURN
L4
LOCALVARIABLE args String[] L0 L4 0
MAXSTACK = 2
MAXLOCALS = 1
如你所见
popint()-POP-因为int属于类别1
poplong()-POP2-因为long属于类别2。双人也一样
popLong()-POP-因为这里Long指的是java.lang.Long,它是一种引用类型。因此属于类别1。您是否检查了堆栈中弹出的值的长度?也许pop2可以达到这个目的。@CoronA您能举一个代码片段的例子吗?
long
和double
值占据操作数堆栈上的两个插槽。要以原子方式删除它们,pop
指令不是很高-因此特殊的pop2
指令。两个后续的pop
可以工作,但会违反原子性约束,对吗?我假设pop2也用于忽略双返回值。
public static main(String[]) : void
L0
LINENUMBER 24 L0
INVOKESTATIC PopVsPop2.popint () : int
POP
L1
LINENUMBER 25 L1
INVOKESTATIC PopVsPop2.poplong () : long
POP2
L2
LINENUMBER 26 L2
INVOKESTATIC PopVsPop2.popLong () : Long
POP
L3
LINENUMBER 27 L3
RETURN
L4
LOCALVARIABLE args String[] L0 L4 0
MAXSTACK = 2
MAXLOCALS = 1