我参考了下面的oracle jvm文档
https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.pop
弹出操作弹出操作数堆栈顶部的值
总体安排
pop表格pop=87(0x57)
操作堆栈...,值→
...
说明从操作数堆栈中弹出顶部值。
除非值是1类计算类型的值(§2.11.1),否则不得使用pop指令。
Pop2操作弹出顶部的一个或两个操作数堆栈值
总体安排
pop2表格pop2=88(0x58)
操作数堆栈格式1:
...,值2,值1→
...
其中,value1和value2均为1类计算类型的值(§2.11.1)。
表格2:
..., 价值→
...
其中值是第2类计算类型的值(§2.11.1)。
说明从操作数堆栈中弹出顶部的一个或两个值。
“从操作数堆栈中弹出顶部的一个或两个值”是什么意思?使用pop2时会有什么例子?
弹出:从堆栈中弹出最上面的单字项并将其丢弃。
POP2:从堆栈中删除两个单字项(例如两个整数,或一个整数和一个对象引用)或一个双字项(即双倍或顺行)。
同样的javadoc提到的问题conatins下面的信息:
表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
正如你所见,只有long和double属于第二类。这是因为所有其他的都是计算32位,而long和double是64位。
下面的例子说明了这一点。
public class PopVsPop2 {
public static int popint(){
return 1;
}
public static long poplong() {
return 1;
}
public static Long popLong() {
return 1L;
}
public static void main(String[] args) {
popint();
poplong();
popLong();
}
上面的javacode有以下生成的字节码:
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。
“从操作数堆栈中弹出顶部的一个或两个值”是什么意思?
这样想1:
>
POP
字节码弹出一个值,该值占用堆栈上的一个x 32位单词。
POP2
字节码要么弹出一个占用两个x 32位字的值,要么弹出两个占用一个x 32位字的值。
当使用POP2
时,什么是示例?
long
或double
值;e、 g.丢弃方法调用产生的不需要的long
结果,或int
值
请注意,当前一代Oracle/OpenJDKjavac
编译器不会向POP2发出POP2
to POP2值。如果堆栈上有两个32位的值需要弹出,编译器将发出两条POP
指令。所以,对于普通Java代码,我不能给出案例#2的例子。(但Java或其他语言的第三方编译器可能会使用它,或者人们用其他方式创建字节码。)
我对JVM内部的了解还不够多,无法确定,但是有POP2
的一个可能的原因是,如果您使用两个POP
指令弹出(例如)一个long
,那么在整个序列中,堆栈将处于无效状态。这很容易导致验证错误。
1-这不是严格正确的。堆栈上的值不是严格意义上的32或64位。例如,64位机器上的引用或返回地址是64位...但是它仍然被建模为类别1值。对此的解释是字节码指令集最初被设计为在32位机器上解释。
编写一个包含主方法的java小程序
System.currentTimeMillis();
不要使用此通话的结果。然后字节码看起来像
INVOKESTATIC java/lang/System.currentTimeMillis()J
POP2
系统。currentTimeMillis()
在堆栈上放置一个长值(64位,宽)。然而,这个堆栈内容不再被使用,因此必须弹出它,以便可以访问其他堆栈内容。32位(正常大小)需要一个简单的POP
,64位(宽大小)需要一个POP2
。
所以我和一位面试官(你的标准人力资源经理)谈了他们在面试中真正想要的东西,他提到了一些关于测试JVM指令知识的东西(以及其他很多东西)。 我不知道那是什么,但我以为他说的是字节码指令。 我做了一些研究,似乎在“JVM指令”上找不到任何东西,我只找到了字节码指令的引用,我已经知道了字节码指令。 例如:http://docs.oracle.com/javase/specs/jvms/se7/html/
问题内容: 我已经仔细阅读了有关该主题的 AngularJS 文档,然后摆弄了一条指令。这是jsfiddle。 以下是一些相关的摘要: 从 HTML : 从窗格指令: 我没有几件事: 为什么必须与和一起使用? 我是否还可以直接访问父范围,而不用属性装饰元素? 该文档说: “通常希望通过表达式将数据从隔离的范围传递到父范围” ,但这似乎也可以与双向绑定一起使用。为什么表达途径会更好? 我发现了另一个
我猜这是一个基本的问题,但是为什么没有sload指令呢?为什么你可以加载除了short之外的所有原语?(有saload,但仍然……) 对于:
我仔细阅读了关于这个主题的AngularJS文档,然后随意修改了一个指令。小提琴在这里。 下面是一些相关的片段: > 来自HTML: 在窗格指令中: 有几件事我不明白: 为什么必须使用与和与? 是否也可以直接访问父范围,而不使用属性装饰元素? 文档说“通常希望通过表达式将数据从独立作用域传递到父作用域”,但这似乎也适用于双向绑定。为什么表达式路由会更好? 我找到了另一个显示表达式解的fiddle:
我刚刚开始使用Angular 2。 我想知道Angular 2中的组件和指令有什么区别?