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

dev*_*ium 8 java bytecode

假设我有一Fraction节课:

class Fraction {
    ...

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

    ...
}
Run Code Online (Sandbox Code Playgroud)

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

 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
Run Code Online (Sandbox Code Playgroud)

我试图理解为什么第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
Run Code Online (Sandbox Code Playgroud)

为什么不是这样?

Ted*_*opp 10

当构造函数的字节码开始时,没有Fraction对象.该new指令Fraction从堆中分配一个对象(未初始化),并在堆栈上留下对它的引用.该dup指令使得一个引用可用于调用<init>,而第二个引用用于areturn最后.

  • @devoured elysium`<init>()V`返回`void`而不是'Fraction`. (5认同)
  • 在Java虚拟机规范中指定了方法`<init>`的使用(章节[3.9](http://java.sun.com/docs/books/jvms/second_edition/html/Overview.doc.html#12174) )和[7.8](http://java.sun.com/docs/books/jvms/second_edition/html/Compiling.doc.html#4089)).奇怪的是,它的类型为void的规范在[第4.4.2节](http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html#29292)中被删除: _"[实例初始化方法]必须不返回任何值."_ (2认同)

Tom*_*icz 8

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

new #1 <xyzTestes/system/fraction/Fraction>
Run Code Online (Sandbox Code Playgroud)

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

aload_0
Run Code Online (Sandbox Code Playgroud)

堆栈 :( Fraction仍然未初始化),this

getfield #16 <xyzTestes/system/fraction/Fraction.den>
Run Code Online (Sandbox Code Playgroud)

堆栈 :( Fraction仍然未初始化),this.den

aload_0
getfield #14 <xyzTestes/system/fraction/Fraction.num>
Run Code Online (Sandbox Code Playgroud)

堆栈 :( Fraction仍未初始化)this.den,this.num

invokespecial #27 <xyzTestes/system/fraction/Fraction.<init>>
Run Code Online (Sandbox Code Playgroud)

堆栈:

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

这意味着您将致电:

areturn
Run Code Online (Sandbox Code Playgroud)

在空堆栈上,吹灭JVM.