2012-02-28 39 views
5

Bằng cách "phát hành", tôi có nghĩa là không có tham chiếu đến trình nạp lớp còn lại.Khi nào là finalize được gọi là trên singletons khi một classloader được phát hành?

Chúng tôi đang gặp sự cố trong đó ứng dụng Java EE thường được triển khai lại sẽ chiếm không gian permgen. Phân tích cho thấy rằng một singleton trong ứng dụng Java EE đã chuyển các tham chiếu đến các đối tượng lớp ứng dụng bên ngoài ứng dụng (vi phạm các quy tắc Java EE) và không xóa chúng khi ứng dụng không được triển khai.

Giả sử không có tài liệu tham khảo nào khác còn lại đối với singleton hoặc đối tượng lớp, sẽ finalize() của singleton được gọi khi trình nạp lớp của lớp đó được phát hành? Tôi muốn xóa các tham chiếu trong giới hạn giả mạo ở đó. Hoặc tôi đang ở trong một catch-22 nơi finalize sẽ không được gọi cho đến khi các classloader chính nó có thể được thu gom rác thải - và do đó sẽ không bao giờ được gọi là vì các tài liệu tham khảo bên ngoài rogue?

Câu hỏi chính ở đây có lẽ là:

một đối tượng lớp sẽ được thu gom rác trong trường hợp này, nơi classloader của nó không thể chưa? Điều này có thể phụ thuộc vào đặc điểm kỹ thuật của hành vi của trình nạp lớp hoặc có thể phụ thuộc vào việc triển khai thực hiện.

Tài liệu tham khảo (loại khác! ;-)) sẽ được đánh giá cao nhưng không cần thiết.

+0

Nếu bạn chuyển tài liệu tham khảo của ClassLoaders xem xét sử dụng WeakReference (s) và WeakHashMap thay vì tham chiếu mạnh (thông thường). – Stefan

Trả lời

4

Lớp học có tham chiếu tĩnh với nó, sẽ chỉ đủ điều kiện thu gom rác, nếu trình nạp lớp đủ điều kiện cho GCing và không có tham chiếu nào khác về tính năng này.

Một lớp hoặc giao diện có thể được dỡ xuống khi và chỉ khi trình tải lớp xác định có thể được bộ thu gom rác thu hồi.

http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.7

Bên cạnh đó mỗi lớp có một tham chiếu đến classloader của nó. Vì vậy, một trình nạp lớp không đủ điều kiện cho GCing miễn là có các tham chiếu đến các lớp được nạp bởi nó hoặc các đối tượng của các lớp đó từ một đối tượng không thể thu thập được.

Trình hoàn thiện sẽ chạy một thời gian sau khi một đối tượng đủ điều kiện để thu thập rác và trước khi GC thực tế diễn ra.

Cách tiếp cận tham chiếu đến miễn phí, ngăn chặn GCing, trong trình hoàn thiện không hoạt động. Trình hoàn thiện sẽ không được gọi miễn là các tham chiếu đó tồn tại vì chúng ngăn không cho đối tượng trở nên đủ điều kiện để thu thập rác.Ví dụ: bạn không thể phá vỡ chuỗi tham chiếu này từ bên trong:

singleton instance <--- singleton class <--- class loader <-- 
<-- any class loaded by that class loader <-- any object of such a class 
<-- object loaded by another classloader referencing such an object or class 
+0

Các tham chiếu không phải là singleton (trực tiếp hoặc gián tiếp), do đó vòng lặp tham chiếu không phải là một vấn đề. Điều chính tôi đang cố gắng để hiểu là nếu lớp có thể được GC'd mặc dù có những tài liệu tham khảo bên ngoài xuất sắc cho các lớp khác từ bộ nạp lớp được phát hành này. –

+0

Bạn có ý nghĩa gì khi "phát hành". Trình nạp lớp chỉ trở thành đủ điều kiện cho GCing, nếu tất cả các lớp được nạp bởi nó cũng đủ điều kiện cho GCing vì mọi lớp đều có tham chiếu đến trình nạp lớp của nó. –

+0

Ok, và ClassLoader có một vectơ của tất cả các lớp mà nó đã nạp ... do đó finalizer sẽ không hoạt động bất kể. Cảm ơn nhiều! –

0

Hành vi của finalisers không thay đổi bộ nạp lớp hoặc sử dụng perm gen, mặc dù nó làm cho vấn đề hiệu suất tồi tệ hơn. Các đối tượng không thể được thu thập cho đến sau khi finaliser được chạy. Vì vậy, (đơn giản hóa bằng cách giả sử không đồng thời, và bỏ qua yếu/mềm/phantom) có một hoạt động của GC xác định rằng không có tham chiếu đang hoạt động nào đối với biểu đồ đối tượng bao gồm trình nạp lớp. Các finalisers được thêm vào hàng đợi finaliser và sau đó thực thi. Sau đó, sau một số lần truy cập tiếp theo của GC, bộ nhớ có thể được phục hồi. Điều này đòi hỏi một GC đầy đủ bao gồm trên không gian gen perm, mà nói chung là không thường xuyên và có thể bị vô hiệu hóa.

Dù sao, không sử dụng (tiểu bang) singletons.

+0

Một đối tượng lớp có được thu gom rác trong trường hợp này không thể tải lớp học của nó? Điều này phụ thuộc vào đặc tả của hành vi của trình nạp lớp, hoặc có thể phụ thuộc vào việc triển khai thực hiện. –

+0

@EdStaub - Một lớp KHÔNG BAO GIỜ được thu thập cho đến khi trình nạp lớp của nó có thể được thu thập. Và một trình nạp lớp không bao giờ được thu thập cho đến khi tất cả các lớp mà nó nạp có thể được thu thập. –

+0

Và tài liệu tham khảo tĩnh vẫn có thể truy cập được trong khi lớp học có thể truy cập được. "Thật thú vị," Tomcat sẽ vô hiệu hóa các trường tĩnh. –

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