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]