2010-02-26 21 views
38

Chúng tôi đang tạo nhiều trình nạp lớp con để tải trong nhiều ứng dụng con vào một ứng dụng Java "vùng chứa", tạo mẫu triển khai nóng. Khi classpath của một trình nạp lớp cụ thể đã thay đổi (tức là các jars đã được thêm vào, xóa, cập nhật), trình nạp lớp cũ được bỏ đi (không được tham chiếu) và trình nạp lớp mới được tạo cho classpath mới của các lọ.Khi nào và như thế nào là một trình nạp lớp java được đánh dấu để thu thập rác?

Sau khi cập nhật đường dẫn lớp, kích hoạt triển khai nóng, chúng tôi đã lấy một vùng lưu trữ. Vùng kết xuất (sử dụng bộ phân tích bộ nhớ) chỉ ra rằng các trình nạp lớp cũ không bị thu gom rác. Một số lớp trong trình nạp lớp cha đã lưu vào bộ đệm ẩn các trình nạp lớp cũ. Những điều sau đây được gọi để xóa các bộ nhớ cache sau:

java.lang.ResourceBundle.clearCache(classLoader); 
org.apache.commons.logging.LogFactory.release(classLoader); 
java.beans.Introspector.flushCaches(); 

Ngay cả sau khi xóa bộ đệm trên, trình nạp lớp cũ vẫn không bị thu gom rác. Các tài liệu tham khảo còn lại để classloader bao gồm những điều sau đây:

  • các lớp tải bởi classloader
  • java.lang.Package của tạo ra bởi classloader tự
  • java.lang.ProtectionDomain được tạo ra bởi classloader tự

Tất cả các bên trên là các tham chiếu vòng tròn trong trình nạp lớp, sẽ kích hoạt bộ sưu tập rác. Tôi không chắc tại sao nó không phải. Có ai biết lý do tại sao các trình nạp lớp cũ vẫn không được thu thập rác ngay cả với các tham chiếu vòng tròn?

+0

Bạn sử dụng JVM nào (phiên bản chính xác)? Bạn có sử dụng bất kỳ tùy chọn JVM nào, điều đó có thể ảnh hưởng đến tải lớp không? Bạn có sử dụng bất kỳ thứ gì từ việc triển khai của Sun không? Ứng dụng có thao tác mã byte không? ... Môi trường có thể ảnh hưởng đến việc tải lớp học là gì? – cafebabe

+1

Không liên quan đến câu hỏi chính của bạn, nhưng bạn đã xem xét một cái gì đó như OSGi thay vì làm khuôn khổ của riêng bạn hỗ trợ triển khai nóng? – SteveD

+0

@bfoo Trong các thử nghiệm của chúng tôi, chúng tôi đang sử dụng Java 6. Không có tùy chọn JVM.Chúng tôi không sử dụng bất kỳ điều gì của Sun trong trường hợp đơn giản nhất. Không có thao tác mã byte. – onejigtwojig

Trả lời

15

Tôi luôn nghe nói rằng việc tải xuống Classloader có vấn đề. Họ là theoretically rác thu thập được khi không có tham chiếu đến các trường hợp đối tượng và dỡ lớp là không cần thiết, nhưng trong thực tế nó có vẻ như là vấn đề hơn. Tài liệu tham khảo tinh tế có thể bị rò rỉ và ngăn không cho Classloader bị thu hồi. Trong các máy chủ ứng dụng, sau nhiều chu kỳ redeploy, đôi khi tôi có một số OutOfMemoryError: PermGen space.

Tất cả những gì để nói rằng tôi đoán có một tài liệu tham khảo khó chịu ở đâu đó ngăn không cho nó được thu thập - có thể bộ phân tích bộ nhớ không theo đúng liên kết. Nó có vẻ như tất cả điều này có thể xảy ra, như được mô tả trong những bài viết này:

Ngoài ra, tôi không biết chính xác những gì bạn đang làm, nhưng nếu bạn có thể chờ đợi JDK 7, bạn có thể xem AnonymousClassLoader. Họ sẽ được giới thiệu để hỗ trợ tốt hơn ngôn ngữ năng động, như được giải thích trong bài viết này:

Tôi hy vọng nó sẽ giúp bạn.

+0

Một ứng dụng phụ rất đơn giản. Thư viện bên thứ ba duy nhất mà nó sử dụng là log4j. Không có gì khác. Phần còn lại là API JDK cơ bản. Nó cũng sử dụng lớp ResourceBundle giữ cache. Sau khi gọi clearCache(), các tham chiếu đó đã biến mất, nhưng nó vẫn không thu gom rác. Nhưng nhờ câu trả lời :) – onejigtwojig

+0

oh và bằng cách này, các liên kết tuyệt vời! – onejigtwojig

+0

Tôi chỉ có thể đề xuất thử với ứng dụng phụ đơn giản nhất (nói với một lớp) và sau đó thêm nhiều lớp và phụ thuộc hơn để xem tại điểm nào nó dừng GC của trình nạp lớp. Nhưng tôi biết nó có thể cực kỳ tốn thời gian. BTW, Frank Kievet cũng viết những bài viết thú vị về các giao dịch XA, nếu bạn quan tâm. – ewernli

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