2012-01-12 28 views
11

Tôi biết rằng vấn đề này đã được khoảng ít nhất 3 năm (Issue 92), nhưng tôi vẫn không hài lòng với tình trạng hiện tại của nó. Tôi cũng biết rằng điều này không ảnh hưởng đến Tomcat nếu bạn khởi động lại sau khi triển khai lại (như được đề xuất trong Guice + Tomcat potential memory leak).Guice 3.0 + Tomcat 7.0 = rò rỉ bộ nhớ ClassLoader

Vấn đề của tôi là tôi đang gặp phải lỗi OutOfMemoryError: PermGen sau một số lần triển khai lại. Lưu ý rằng tôi không sử dụng bộ sưu tập google một cách rõ ràng, tôi chỉ sử dụng Guice 3.0 (thông qua maven). Sau khi phân tích các bãi đống, tôi vẫn thấy rằng luồng com.google.inject.internal.Finalizer vẫn hoạt động, giữ một tham chiếu đến WebappClassLoader của Tomcat, do đó cản trở việc thu gom rác.

Nếu tôi thực sự yêu cầu việc triển khai lại mà không cần khởi động lại và đang sử dụng Guice thì sao? Những lựa chọn của tôi là gì?

Trả lời

9

Vâng, không có ai ở đó để giúp tôi, vì vậy đây là những gì tôi đã học:

Các chủ đề finalizer được khởi động bởi FinalizableReferenceQueue (FRQ). Có một tham chiếu cứng (tĩnh) đối với FRQ trong MapMaker. WebAppClassLoader không phải là rác được thu thập bởi vì MapMaper vẫn còn xung quanh do tham chiếu cứng.

Các mã sau giải quyết vấn đề của tôi:

final Class<?> queueHolderClass = 
    Class.forName("com.google.inject.internal.util.$MapMaker$QueueHolder"); 
final Field queueField = queueHolderClass.getDeclaredField("queue"); 
// make MapMaker.QueueHolder.queue accessible 
queueField.setAccessible(true); 
// remove the final modifier from MapMaker.QueueHolder.queue 
final Field modifiersField = Field.class.getDeclaredField("modifiers"); 
modifiersField.setAccessible(true); 
modifiersField.setInt(queueField, queueField.getModifiers() & ~Modifier.FINAL); 
// set it to null 
queueField.set(null, null); 

Đây là vi phạm mã (com.google.inject.internal.util.MapMaker):

/** Wrapper class ensures that queue isn't created until it's used. */ 
private static class QueueHolder { 
    static final FinalizableReferenceQueue queue = new FinalizableReferenceQueue(); 
} 

Sau khi làm điều này, thread finalizer duyên dáng chết.

+0

Đây là báo cáo lỗi cho sự cố này: http://code.google.com/p/google-guice/issues/detail?id=288 – Gili