Why does the following code translate to a new + dup op instructions in java bytecode?

岁酱吖の 提交于 2019-12-10 03:30:56

问题


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?


回答1:


When the bytecode for the constructor starts, there is no Fraction object. The new instruction allocates a Fraction object (uninitialized) from the heap and leaves a reference to it on the stack. The dup instruction is so that one reference can be used to call <init> and the second used for the areturn at the end.




回答2:


Your bytecode is incorrect. Let's step through it:

new #1 <xyzTestes/system/fraction/Fraction>

Stack: Fraction instance (uninitialized, only a pointer to memory)

aload_0

Stack: Fraction (still uninitialized), this

getfield #16 <xyzTestes/system/fraction/Fraction.den>

Stack: Fraction (still uninitialized), this.den

aload_0
getfield #14 <xyzTestes/system/fraction/Fraction.num>

Stack: Fraction (still uninitialized), this.den, this.num

invokespecial #27 <xyzTestes/system/fraction/Fraction.<init>>

Stack:

This is crucial. All invoke methods require the stack to contain this + all arguments. Both this and arguments are taken from the stack. After the invocation only a return value (if any) is placed on the stack. <init> has a void return type.

This means you will call:

areturn

On an empty stack, blowing out the JVM.



来源:https://stackoverflow.com/questions/8594657/why-does-the-following-code-translate-to-a-new-dup-op-instructions-in-java-byt

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!