假设我有一个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
为什么不是这样?
答案 0 :(得分:10)
当构造函数的字节码开始时,没有Fraction对象。 new
指令从堆中分配Fraction
对象(未初始化),并在堆栈上留下对它的引用。 dup
指令可以使用一个引用来调用<init>
,最后一个引用用于areturn
。
答案 1 :(得分:8)
您的字节码不正确。让我们一步一步:
new #1 <xyzTestes/system/fraction/Fraction>
堆栈:Fraction
实例(未初始化,只是指向内存的指针)
aload_0
堆叠:Fraction
(尚未初始化),this
getfield #16 <xyzTestes/system/fraction/Fraction.den>
堆叠:Fraction
(尚未初始化),this.den
aload_0
getfield #14 <xyzTestes/system/fraction/Fraction.num>
堆叠:Fraction
(尚未初始化),this.den
,this.num
invokespecial #27 <xyzTestes/system/fraction/Fraction.<init>>
<强>堆栈强>:
这很重要。所有invoke
方法都要求堆栈包含this
+所有参数。 this
和参数都来自堆栈。调用后,只有一个返回值(如果有)放在堆栈上。 <init>
的回复类型为void
。
这意味着您将致电:
areturn
在空堆栈上,吹灭JVM。