2012-02-09 17 views
12

Dự án của chúng tôi thực hiện một số công cụ bytecode Java. Và chúng tôi tình cờ gặp một số hành vi kỳ lạ. Giả sử đoạn mã sau:Sự khác biệt trong bytecode java được sản xuất bởi trình biên dịch của Oracle và Eclipse

public void a() { 
    new Integer(2); 
    } 

Oracle javac biên dịch trên vào bytecode sau:

0: new #2; //class java/lang/Integer 
    3: dup 
    4: iconst_2 
    5: invokespecial #3; //Method java/lang/Integer."<init>":(I)V 
    8: pop 
    9: return 

và trình biên dịch của Eclipse vào:

0: new #15; //class java/lang/Integer 
    3: iconst_2 
    4: invokespecial #17; //Method java/lang/Integer."<init>":(I)V 
    7: return 

Như bạn thấy, Oracle trình biên dịch tạo "dup" sau "mới", trong khi Eclipse thì không. Đó là hoàn toàn chính xác trong trường hợp sử dụng này, như trường hợp Integer mới được tạo ra không được sử dụng ở tất cả, vì vậy không có "dup" là bắt buộc.

Câu hỏi của tôi là:

  1. Có một số tổng quan về sự khác nhau giữa các trình biên dịch khác nhau? Bài viết/bài đăng trên blog?
  2. Tôi có thể kết luận một cách an toàn, rằng nếu không có "dup" giữa "mới" và "invokespecial" thì đối tượng không được sử dụng sau khi khởi tạo?
+4

Mục tiêu của bạn với việc thiết lập bytecode là gì? Sự khác biệt này có gây ra vấn đề cho bạn không? Lưu ý rằng không có sự đảm bảo về những gì bytecode chính xác một trình biên dịch Java sẽ tạo ra.Hoàn toàn có thể là trong một phiên bản tương lai, Oracle 'javac' sẽ tạo ra một cái gì đó khác với những gì bạn thấy bây giờ - vì vậy nó không phải là ý tưởng hay khi viết một chương trình phụ thuộc rất nhiều vào bytecode chính xác do trình biên dịch tạo ra. – Jesper

+0

Bạn có sử dụng JDK khác cho Eclipse không? – Nishant

Trả lời

3
  1. Tôi có thể một cách an toàn kết luận, rằng nếu không có "dup" giữa "mới" và "invokespecial", sau đó đối tượng không được sử dụng sau khi khởi tạo?

Tôi không chắc chắn những gì bạn có nghĩa là chính xác, nhưng một tham chiếu đến đối tượng được tạo ra có thể được lưu trữ ở đâu đó bởi các nhà xây dựng. Do đó, phương thức gọi có thể không sử dụng đối tượng sau khi khởi tạo nhưng đối tượng vẫn có thể truy cập được và có thể do đó không thể thu gom rác.

6

Nếu có một dup giữa mớiinvokespecial sau đó các đối tượng thường sử dụng sau khi biên dịch. Ví dụ, lĩnh vực khởi thường là một chuỗi các mới, dup, invokespecial & putfield. Tuy nhiên, trong ví dụ của bạn, lệnh cuối cùng là pop làm sạch đối tượng khỏi ngăn xếp - đây là cách bạn có thể giả định rằng đối tượng này không được sử dụng.

+0

Như được chỉ ra bởi A.H., cửa sổ pop chỉ có nghĩa là nó không được người gọi sử dụng. Các đối tượng chính nó có thể cho đi tài liệu tham khảo cho chính nó trong ctor. – Antimony

1

Đi qua tài liệu tham khảo này sẽ phá vỡ mô hình này một chút

public class Bump { 

    Test t; 

    public Bump() { 
     new Test(this); 
    } 
    public void setT(Test t) { 
     this.t = t; 
    } 
    } 

Và sau đó người ta có thể sử dụng này để lưu trữ kết quả trở lại :)

public class Test { 

    Bump b; 

    public Test(Bump b) { 
     this.b = b; 
     b.setT(this); 
    } 
    } 

Have fun :)

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