为什么以下代码转换为java字节码中的新+ dup op指令?

假设我有一个Fraction类:

 class Fraction { ... /** Invert current fraction */ public Fraction inverse() { return new Fraction(den,num); } ... } 

这就是上述方法的字节码结果如下:

  0 new #1  3 dup 4 aload_0 5 getfield #16  8 aload_0 9 getfield #14  12 invokespecial #27 <xyzTestes/system/fraction/Fraction.> 15 areturn 

我试图理解为什么第3位的教学首先放在那里。 我要说我们只需要做以下工作就可以了:

  new #1  aload_0 getfield #16  aload_0 getfield #14  invokespecial #27 <xyzTestes/system/fraction/Fraction.> areturn 

为什么不是这样?

当构造函数的字节码开始时,没有Fraction对象。 new指令从堆中分配一个Fraction对象(未初始化),并在堆栈上留下对它的引用。 dup指令是这样的,一个引用可用于调用 ,第二个引用用于最后的结果。

你的字节码不正确。 让我们一步一步:

 new #1  

堆栈Fraction实例(未初始化,仅指向内存的指针)

 aload_0 

StackFraction (仍然未初始化), this

 getfield #16  

StackFraction (仍然未初始化), this.den

 aload_0 getfield #14  

StackFraction (仍然未初始化), this.denthis.num

 invokespecial #27 > 

堆栈

这很关键。 所有invoke方法都要求堆栈包含this +所有参数。 this和参数都来自堆栈。 在调用之后,只有一个返回值(如果有)放在堆栈上。 具有void返回类型。

这意味着您将致电:

 areturn 

在空堆栈上,吹灭JVM。