2011-12-21 31 views
8

Hãy nói rằng tôi có một lớp Fraction:Tại sao đoạn mã sau dịch sang một hướng dẫn + dup op mới trong bytecode java?

class Fraction { 
    ... 

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

    ... 
} 

Và đây là những gì bytecode của các phương pháp trên hóa ra là:

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 

Tôi đang cố gắng để hiểu tại sao hướng dẫn ở vị trí 3 đã được đặt ở nơi đầu tiên. Tôi muốn nói rằng chúng tôi chỉ cần thực hiện những điều sau để làm cho nó hoạt động:

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 

Tại sao lại không như vậy?

Trả lời

10

Khi mã byte cho hàm khởi tạo bắt đầu, không có đối tượng Phân số. Lệnh new phân bổ một đối tượng Fraction (chưa được khởi tạo) từ vùng heap và để lại một tham chiếu đến nó trên ngăn xếp. Hướng dẫn dup để có thể sử dụng một tham chiếu để gọi <init> và tham chiếu thứ hai được sử dụng cho số areturn ở cuối.

+0

invokespecial sẽ không đặt tham chiếu đến Fraction trên stack, sau đó? –

+5

@devoured elysium '() V' trả về' void' không phải là 'Phân số'. –

+0

Meh, bạn nói đúng. –

8

Mã byte của bạn không chính xác. Chúng ta hãy bước qua nó:

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

stack: Fraction dụ (chưa được khởi tạo, chỉ có một con trỏ tới bộ nhớ)

aload_0 

stack: Fraction (vẫn chưa được khởi tạo), this

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

Ngăn xếp: Fraction (vẫn chưa được khởi tạo), this.den

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

stack: Fraction (vẫn chưa được khởi tạo), this.den, this.num

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

stack:

này là rất quan trọng. Tất cả các phương thức invoke yêu cầu ngăn xếp để chứa this + tất cả đối số. Cả hai this và đối số được lấy từ ngăn xếp. Sau khi gọi, chỉ có một giá trị trả về (nếu có) được đặt trên ngăn xếp. <init> có loại trả về void.

này có nghĩa là bạn sẽ gọi:

areturn 

Trên một ngăn xếp rỗng, thổi ra JVM.

Các vấn đề liên quan