2013-01-23 7 views
13

Có bất kỳ chi tiết nào về việc có hay không một đối tượng được làm sạch bằng cách sử dụng finalize() nếu hàm tạo của đối tượng đów là một ngoại lệ.Có thể hoàn thành được gọi sau khi một nhà xây dựng ném một ngoại lệ?

Khi phương pháp này được gọi là bệnh nghiêm trọng được xác định. Theo hướng dẫn sử dụng:

Ngôn ngữ lập trình Java không đảm bảo chủ đề nào sẽ gọi phương thức hoàn thiện cho bất kỳ đối tượng cụ thể nào. Tuy nhiên, nó được đảm bảo, tuy nhiên, , rằng chuỗi gọi kết thúc sẽ không giữ bất kỳ khóa đồng bộ hóa nào có thể nhìn thấy người dùng khi hoàn thành được gọi. Nếu một ngoại lệ không bị bắt buộc là được ném bởi phương thức hoàn thành, ngoại lệ là bỏ qua và hoàn tất đối tượng đó chấm dứt.

http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#finalize%28%29

Tôi đã không thể kích hoạt các phương pháp Finalize theo cách này. Có ai biết nếu nó là garunteed không được gọi là hoặc nếu nó là trong một số trường hợp được gọi là sau khi constructor không khởi tạo đối tượng (thew một ngoại lệ).

Tôi hỏi điều này vì tôi có một đối tượng không được làm sạch hai lần. Tôi đang cố gắng để hiểu nếu nó là an toàn để làm sạch trước khi ném ngoại lệ hoặc nếu tôi phải để lại một dấu hiệu cho finalize() để có hiệu quả bỏ qua và không phải làm gì.

+3

+1 tôi nghi ngờ nó là một cái gì đó bạn sẽ cần phải kiểm tra như các JVM khác nhau có thể hành xử khác nhau. –

+0

Sử dụng 'finalize' là điều xấu. –

+1

@Peter JLS là khá cụ thể, một đối tượng là finalizable một khi constructor cho [base] Object được hoàn tất thành công. –

Trả lời

10

thử nghiệm của tôi cho thấy rằng nó có thể

public class Test1 { 

    Test1() { 
     throw new RuntimeException(); 
    } 

    @Override 
    protected void finalize() throws Throwable { 
     System.out.println("finalized"); 
    } 

    public static void main(String[] args) throws Exception { 
     try { 
      new Test1(); 
     } catch (RuntimeException e) { 
      e.printStackTrace(); 
     } 
     System.gc(); 
     Thread.sleep(1000); 
    } 
} 

in

java.lang.RuntimeException 
    at test.Test1.<init>(Test1.java:13) 
    at test.Test1.main(Test1.java:24) 
finalized 

nó là trên Java HostSpot Khách hàng VM 1.7.0_03

+0

Điều đó rất hữu ích! Bạn có thể chỉnh sửa câu trả lời của bạn mà JVM bạn đã thử này và tôi sẽ chấp nhận nó. Cảm ơn nhiều! –

+0

điều này là do hàm ý super() không ném ngoại lệ. –

7

Theo phần 12.6.1. Implementing Finalization của JLS:

Đối tượng o là không thể hoàn thành cho đến khi hàm tạo của nó đã viện dẫn hàm tạo cho đối tượng trên o và lời gọi đó đã hoàn tất thành công (nghĩa là, không ném một ngoại lệ).

Nếu constructor của bạn ném một ngoại lệ sau các nhà xây dựng đối tượng hoàn tất, sau đó đối tượng của bạn nên được finalizable, vì vậy finalize() có thể vẫn được gọi.

Có một ví dụ điển hình cho việc xây dựng đối tượng trong phần 12.5. Creation of New Class Instances hiển thị chính xác khi nào hàm tạo của đối tượng được gọi.

+0

Điều đó có nghĩa là trong lớp X X() {super();} cuộc gọi super() tới Object đã hoàn thành mà không có ngoại lệ. Lớp Object có mã keo để đăng ký phân bổ heap, được cấp phát mới, để thu thập rác. –

1

Để chứng minh rõ ràng hơn:

public class Test1 { 

    public static class LifeBoat extends RuntimeException 
    { 
     private Test1 passenger; 
     public Test1 getPassenger(){return passenger;} 
     public LifeBoat(Test1 passenger){this.passenger=passenger;} 
    } 

    Test1() { 
     super(); //once this is finished, there is an Object to GC per JLS 12.6.1. 
     throw new LifeBoat(this); 
    } 

    @Override 
    protected void finalize() throws Throwable { 
     System.out.println("finalized"); 
    } 

    public static void main(String[] args) throws Exception { 
     try { 
      new Test1(); 
     } catch (LifeBoat e) { 
      Test1 obj; 
      obj=e.getPassenger(); 
      System.out.println(obj); 
     } 
     System.gc(); 
     Thread.sleep(1000); 
    } 
} 

in

java.lang.RuntimeException 
    at test.Test1.<init>(Test1.java:13) 
    at test.Test1.main(Test1.java:24) 
[email protected] 
finalized