diff --git a/src/java/org/apache/commons/logging/impl/ServletContextCleaner.java b/src/java/org/apache/commons/logging/impl/ServletContextCleaner.java index 22d137a..426fc4b 100644 --- a/src/java/org/apache/commons/logging/impl/ServletContextCleaner.java +++ b/src/java/org/apache/commons/logging/impl/ServletContextCleaner.java @@ -68,6 +68,33 @@ public class ServletContextCleaner implements ServletContextListener { // Walk up the tree of classloaders, finding all the available // LogFactory classes and releasing any objects associated with // the tccl (ie the webapp). + // + // When there is only one LogFactory in the classpath, and it + // is within the webapp being undeployed then there is no problem; + // garbage collection works fine. + // + // When there are multiple LogFactory classes in the classpath but + // parent-first classloading is used everywhere, this loop is really + // short. The first instance of LogFactory found will + // be the highest in the classpath, and then no more will be found. + // This is ok, as with this setup this will be the only LogFactory + // holding any data associated with the tccl being released. + // + // When there are multiple LogFactory classes in the classpath and + // child-first classloading is used in any classloader, then multiple + // LogFactory instances may hold info about this TCCL; whenever the + // webapp makes a call into a class loaded via an ancestor classloader + // and that class calls LogFactory the tccl gets registered in + // the LogFactory instance that is visible from the ancestor + // classloader. However the concrete logging library it points + // to is expected to have been loaded via the TCCL, so the + // underlying logging lib is only initialised/configured once. + // These references from ancestor LogFactory classes down to + // TCCL classloaders are held via weak references and so should + // be released but there are circumstances where they may not. + // Walking up the classloader ancestry ladder releasing + // the current tccl at each level tree, though, will definitely + // clear any problem references. ClassLoader loader = tccl; while (loader != null) { // Load via the current loader. Note that if the class is not accessable