We are creating multiple child classloaders to load in multiple subapplications into a Java application "container", prototyping hot deployment. When the classpath of a particular classloader has changed (i.e. jars have been added, deleted, updated), the old classloader is thrown away (unreferenced) and a new classloader is created for the new classpath of jars.
After updating the classpath, triggering the hot deployment, we took a heap dump. The heap dump (using Memory Analyzer) indicates that the old classloaders were not being garbage collected. Certain classes in the parent classloader were caching the old classloaders. The following things were invoked to clear these caches:
java.lang.ResourceBundle.clearCache(classLoader);
org.apache.commons.logging.LogFactory.release(classLoader);
java.beans.Introspector.flushCaches();
Even after clearing the above caches, the old classloader were still not being garbage collected. The remaining references to the classloader included the following:
- the classes loaded by the classloader
- java.lang.Package's created by the classloader itself
- java.lang.ProtectionDomain created by the classloader itself
All the above are circular references within the classloader, which should trigger a garbage collection. I'm not sure why it is not. Does anybody know why the old classloaders are still not being garbage collected even with the circular references?