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

发布于 2024-12-22 06:23:46 字数 930 浏览 3 评论 0原文

假设我有一个 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

终弃我 2024-12-29 06:23:46

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

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.

想念有你 2024-12-29 06:23:46

您的字节码不正确。让我们逐步了解一下:

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

Stack: Fraction 实例(未初始化,只是指向内存的指针)

aload_0

Stack: Fraction (仍未初始化),this

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

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

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

Stack: 分数 (尚未初始化)、this.denthis.num

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

Stack

这一点至关重要。所有 invoke 方法都要求堆栈包含 this + 所有参数。 this 和参数都是从堆栈中获取的。调用后,仅将返回值(如果有)放入堆栈中。 具有 void 返回类型。

这意味着您将调用:

areturn

在空堆栈上,吹灭 JVM。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文