2011-12-21 36 views
8

比方說,我有一個Fraction類:爲什麼下面的代碼轉換爲java字節碼中的新增重複操作指令?

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 

爲什麼不是這樣?

回答

10

當構造函數的字節碼開始時,沒有Fraction對象。指令new從堆中分配一個Fraction對象(未初始化),並在堆棧上留下引用。 dup指令可以用來調用<init>,最後一個用於areturn

+0

invokespecial將不會引用堆棧中的分數,然後呢? – 2011-12-21 18:41:21

+5

@devoured elysium'()V'返回'void'而不是'Fraction'。 – 2011-12-21 18:45:11

+0

呃,你說得對。 – 2011-12-21 18:45:38

8

你的字節碼不正確。讓我們通過它一步:

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

堆棧Fraction實例(未初始化,只是一個指針到內存)

aload_0 

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

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

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

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

堆棧Fraction(仍然未初始化),this.denthis.num

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

堆棧

這是至關重要的。所有invoke方法都要求堆棧包含this +所有參數。 this和參數都從堆棧中取出。調用之後,只有一個返回值(如果有的話)放在堆棧上。 <init>有一個void返回類型。

這意味着你將撥打:

areturn 

在一個空棧,吹出來的JVM。

相關問題