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:
Here's the offending code (
com.google.inject.internal.util.MapMaker
):After doing this, the Finalizer thread gracefully dies.