I know that this problem has been around for at least 3 yeears (Issue 92), but I'm still not satisfied with the current state of it. I am also aware that this does not affect Tomcat if you do restart after redeploying (as suggested in Guice + Tomcat potential memory leak).
My problem is that I am experiencing OutOfMemoryError: PermGen
errors after some redeployments. Notice that I am not using google-collections explicitly, I am only using Guice 3.0 (via maven). After analyzing heap dumps, I still see that the thread com.google.inject.internal.Finalizer
is still active, keeps a reference to Tomcat's WebappClassLoader, thus hindering garbage collection.
What if I actually require redeployments without restarting and am using Guice? What are my options?
Well, no one was there to help me, so here's what I learned:
The Finalizer thread is started by the FinalizableReferenceQueue (FRQ). There is a hard (static) reference to the FRQ in MapMaker. The WebAppClassLoader was not garbage collected because MapMaper was still around due to the hard reference.
The following code solved my problem:
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);
Here's the offending code (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();
}
After doing this, the Finalizer thread gracefully dies.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With