Author: skitching
Date: Thu Jan 19 04:16:56 2006
New Revision: 370464

URL: http://svn.apache.org/viewcvs?rev=370464&view=rev
Log:
Walk the entire hierarchy of ClassLoaders, releasing memory for the
current webapp from each copy of LogFactory found.

Modified:
    
jakarta/commons/proper/logging/trunk/src/java/org/apache/commons/logging/impl/ServletContextCleaner.java

Modified: 
jakarta/commons/proper/logging/trunk/src/java/org/apache/commons/logging/impl/ServletContextCleaner.java
URL: 
http://svn.apache.org/viewcvs/jakarta/commons/proper/logging/trunk/src/java/org/apache/commons/logging/impl/ServletContextCleaner.java?rev=370464&r1=370463&r2=370464&view=diff
==============================================================================
--- 
jakarta/commons/proper/logging/trunk/src/java/org/apache/commons/logging/impl/ServletContextCleaner.java
 (original)
+++ 
jakarta/commons/proper/logging/trunk/src/java/org/apache/commons/logging/impl/ServletContextCleaner.java
 Thu Jan 19 04:16:56 2006
@@ -17,8 +17,11 @@
 
 package org.apache.commons.logging.impl;
 
-import javax.servlet.ServletContextListener;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
 import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
 
 import org.apache.commons.logging.LogFactory;
 
@@ -48,6 +51,8 @@
  */
 
 public class ServletContextCleaner implements ServletContextListener {
+
+    private Class[] RELEASE_SIGNATURE = {ClassLoader.class};
     
     /**
      * Invoked when a webapp is undeployed, this tells the LogFactory
@@ -55,7 +60,47 @@
      * contextClassloader.
      */
     public void contextDestroyed(ServletContextEvent sce) {
-        LogFactory.release(Thread.currentThread().getContextClassLoader());
+        ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+
+        Object[] params = new Object[1];
+        params[0] = tccl;
+
+        // Walk up the tree of classloaders, finding all the available
+        // LogFactory classes and releasing any objects associated with
+        // the tccl (ie the webapp).
+        ClassLoader loader = tccl;
+        while (loader != null) {
+            // Load via the current loader. Note that if the class is not 
accessable
+            // via this loader, but is accessable via some ancestor then that 
class
+            // will be returned.
+            try {
+                Class logFactoryClass = 
loader.loadClass("org.apache.commons.logging.LogFactory");
+                Method releaseMethod = logFactoryClass.getMethod("release", 
RELEASE_SIGNATURE);
+                releaseMethod.invoke(null, params);
+                loader = logFactoryClass.getClassLoader().getParent();
+            } catch(ClassNotFoundException ex) {
+                // Neither the current classloader nor any of its ancestors 
could find
+                // the LogFactory class, so we can stop now.
+                loader = null;
+            } catch(NoSuchMethodException ex) {
+                // This is not expected; every version of JCL has this method
+                System.err.println("LogFactory instance found which does not 
support release method!");
+                loader = null;
+            } catch(IllegalAccessException ex) {
+                // This is not expected; every ancestor class should be 
accessable
+                System.err.println("LogFactory instance found which is not 
accessable!");
+                loader = null;
+            } catch(InvocationTargetException ex) {
+                // This is not expected
+                System.err.println("LogFactory instance release method 
failed!");
+                loader = null;
+            }
+        }
+        
+        // Just to be sure, invoke release on the LogFactory that is visible 
from
+        // this ServletContextCleaner class too. This should already have been 
caught
+        // by the above loop but just in case...
+        LogFactory.release(tccl);
     }
     
     /**



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to