2013-01-24 21 views
9

Trong java, việc thu thập rác sẽ gọi phương thức hoàn tất trên đối tượng x nếu không có tham chiếu mạnh trỏ tới x và x đủ điều kiện để thu thập rác. Điều gì sẽ xảy ra nếu phương thức hoàn thiện không bao giờ chấm dứt, điều này có gây ra rò rỉ bộ nhớ không?Java: phương thức hoàn thiện không xác định để tạo rò rỉ bộ nhớ

 
public class X{ 
    protected void finalize(){ 
    while(true){} 
    } 
} 
+7

Điều gì ngăn bạn không dùng thử? –

Trả lời

2

Có.
Cũng bên trong phương thức finalize nếu bạn cung cấp tham chiếu hợp lệ cho đối tượng mà phương thức finalize được gọi, Java sẽ không thu thập rác đối tượng cũng sẽ không gọi phương thức finalize lần nữa vì nó được gọi chỉ một lần.

2

Chắc chắn. Bộ nhớ sẽ được deallocated sau khi hoàn thành phương thức trả về.Và nếu finalize của bạn không bao giờ trả về, momory sẽ không được deallocated.

Google về sự phục sinh trong thu gom rác thải và bạn sẽ nhận được các trường hợp khác nhau mà phương pháp Finalize không đảm bảo gc

6

Có nó sẽ, dễ dàng để kiểm tra

public class X { 

    protected void finalize() { 
     while (true) { 
     } 
    } 

    public static void main(String[] args) throws Exception { 
     while (true) { 
      new X(); 
     } 
    } 
} 

sau một thời gian tôi đã

Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "main" 

khi tôi xóa xong() thử nghiệm không bao giờ dừng lại. Lưu ý rằng phải mất một thời gian trước khi JVM đi oom

BTW đó là đủ để chạy thử nghiệm này

public class X { 
    byte[] a = new byte[100 * 1000 * 1000]; 

    protected void finalize() { 
     System.out.println(); 
    } 

    public static void main(String[] args) throws Exception { 
     while (true) { 
      new X(); 
     } 
    } 
} 

để phá vỡ GC

Exception in thread "main" 
java.lang.OutOfMemoryError: Java heap space 
    at test.X.<init>(X.java:5) 
    at test.X.main(X.java:13) 

bình luận ra //System.out.println (); và nó hoạt động không ngừng

+1

+1 để thực sự dùng thử! =) – pcalcao

+0

Điều thú vị là, trên mac os x, chương trình chỉ kết thúc mà không có thông báo lỗi. Tôi đã thêm xử lý ngoại lệ xung quanh vòng lặp while, nhưng không có ngoại lệ nào bị bắt. Tôi cũng đã thêm một số đầu ra từ finalizer, chỉ để xem liệu nó đã từng được gọi ra chưa, nhưng không cái nào được hiển thị. – Henrik

+0

Rất tiếc, bạn không bao giờ biết, đã sửa câu trả lời của tôi là "Có, nó có thể ..." –

0

Nó sẽ chặn java.lang.ref.Finalizer $ FinalizerThread (The Secret Life Of The Finalizer), thể hiện của tất cả các lớp thực hiện phương thức hoàn thiện sẽ bị chặn trong java.lang.ref.Finalizer.ReferenceQueue. Bạn tiếp tục tạo đối tượng mới với 'finalize', bộ nhớ sẽ bị cạn kiệt bởi những đối tượng đang đợi để thực thi finalize. Nếu có một đống kết xuất, bạn sẽ thấy các đối tượng được giữ lại bởi java.lang.ref.Finalizer, xem ví dụ bên dưới (đây là một trường hợp thực). enter image description here