为什么以下代码会转换为新的 + java字节码中的dup op指令?
假设我有一个 Fraction
类:
class Fraction {
...
/** Invert current fraction */
public Fraction inverse() {
return new Fraction(den,num);
}
...
}
这就是上述方法的字节码:
0 new #1 <xyzTestes/system/fraction/Fraction>
3 dup
4 aload_0
5 getfield #16 <xyzTestes/system/fraction/Fraction.den>
8 aload_0
9 getfield #14 <xyzTestes/system/fraction/Fraction.num>
12 invokespecial #27 <xyzTestes/system/fraction/Fraction.<init>>
15 areturn
我试图理解为什么位置 3 处的指令首先被放在那里。我想说我们只需要执行以下操作即可使其发挥作用:
new #1 <xyzTestes/system/fraction/Fraction>
aload_0
getfield #16 <xyzTestes/system/fraction/Fraction.den>
aload_0
getfield #14 <xyzTestes/system/fraction/Fraction.num>
invokespecial #27 <xyzTestes/system/fraction/Fraction.<init>>
areturn
为什么不是这样?
Let's say I have a Fraction
class:
class Fraction {
...
/** Invert current fraction */
public Fraction inverse() {
return new Fraction(den,num);
}
...
}
And this is what the bytecode of the above method turns out to be:
0 new #1 <xyzTestes/system/fraction/Fraction>
3 dup
4 aload_0
5 getfield #16 <xyzTestes/system/fraction/Fraction.den>
8 aload_0
9 getfield #14 <xyzTestes/system/fraction/Fraction.num>
12 invokespecial #27 <xyzTestes/system/fraction/Fraction.<init>>
15 areturn
I'm trying to understand why instruction at position 3 was put there in the first place. I'd say we'd only need to do the following to make it work:
new #1 <xyzTestes/system/fraction/Fraction>
aload_0
getfield #16 <xyzTestes/system/fraction/Fraction.den>
aload_0
getfield #14 <xyzTestes/system/fraction/Fraction.num>
invokespecial #27 <xyzTestes/system/fraction/Fraction.<init>>
areturn
Why is not so?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
当构造函数的字节码开始时,没有 Fraction 对象。
new
指令从堆中分配一个Fraction
对象(未初始化),并在堆栈上留下对其的引用。dup
指令的作用是,一个引用可用于调用
,第二个引用可用于最后的areturn
。When the bytecode for the constructor starts, there is no Fraction object. The
new
instruction allocates aFraction
object (uninitialized) from the heap and leaves a reference to it on the stack. Thedup
instruction is so that one reference can be used to call<init>
and the second used for theareturn
at the end.您的字节码不正确。让我们逐步了解一下:
Stack:
Fraction
实例(未初始化,只是指向内存的指针)Stack:
Fraction
(仍未初始化),this
Stack:
Fraction
(仍未初始化),this.den
Stack:
分数
(尚未初始化)、this.den
、this.num
Stack:
这一点至关重要。所有
invoke
方法都要求堆栈包含this
+ 所有参数。this
和参数都是从堆栈中获取的。调用后,仅将返回值(如果有)放入堆栈中。
具有void
返回类型。这意味着您将调用:
在空堆栈上,吹灭 JVM。
Your bytecode is incorrect. Let's step through it:
Stack:
Fraction
instance (uninitialized, only a pointer to memory)Stack:
Fraction
(still uninitialized),this
Stack:
Fraction
(still uninitialized),this.den
Stack:
Fraction
(still uninitialized),this.den
,this.num
Stack:
This is crucial. All
invoke
methods require the stack to containthis
+ all arguments. Boththis
and arguments are taken from the stack. After the invocation only a return value (if any) is placed on the stack.<init>
has avoid
return type.This means you will call:
On an empty stack, blowing out the JVM.