I'm not sure this will work because when I redeploy the webapp the first call to LogFactory.cacheFactory() shows that the factoryCache is empty. Is it possible that the LogFactory was created by a different ClassLoader and therefore it's statics are invisible to the redeployment of the webapp. But if the LogFactory *did* belong to the old classloader then I would expect it would be GCable along with the Classloader itself.
Kind of a circular argument I think. As a brief aside I found the following code in the WebAppClassLoader.releaseResources() of Tomcat 6, so it looks like some of the well-known caches are being cleared out by Tomcat itself. protected void clearReferences() { // Unregister any JDBC drivers loaded by this classloader Enumeration drivers = DriverManager.getDrivers(); while (drivers.hasMoreElements()) { Driver driver = (Driver) drivers.nextElement(); if (driver.getClass().getClassLoader() == this) { try { DriverManager.deregisterDriver(driver); } catch (SQLException e) { log.warn("SQL driver deregistration failed", e); } } } // Null out any static or final fields from loaded classes, // as a workaround for apparent garbage collection bugs Iterator loadedClasses = ((HashMap) resourceEntries.clone()).values().iterator(); while (loadedClasses.hasNext()) { ResourceEntry entry = (ResourceEntry) loadedClasses.next(); if (entry.loadedClass != null) { Class clazz = entry.loadedClass; try { Field[] fields = clazz.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field field = fields[i]; int mods = field.getModifiers(); if (field.getType().isPrimitive() || (field.getName().indexOf("$") != -1)) { continue; } if (Modifier.isStatic(mods)) { try { field.setAccessible(true); if (Modifier.isFinal(mods)) { if (!((field.getType().getName().startsWith("java.")) || (field.getType().getName().startsWith("javax.")))) { nullInstance(field.get(null)); } } else { field.set(null, null); if (log.isDebugEnabled()) { log.debug("Set field " + field.getName() + " to null in class " + clazz.getName()); } } } catch (Throwable t) { if (log.isDebugEnabled()) { log.debug("Could not set field " + field.getName() + " to null in class " + clazz.getName(), t); } } } } } catch (Throwable t) { if (log.isDebugEnabled()) { log.debug("Could not clean fields for class " + clazz.getName(), t); } } } } // Clear the IntrospectionUtils cache. IntrospectionUtils.clear(); // Clear the classloader reference in common-logging org.apache.juli.logging.LogFactory.release(this); // Clear the classloader reference in the VM's bean introspector java.beans.Introspector.flushCaches(); } Not sure really where to go from here. My previous experience with profilers (I've tried most of them) is that they aren't very good for pinning down problems like this. Getting answers to a question like "where/what is my Classloader reference being held from/by?" is difficult or impossible. Maybe I was using them wrong. If things have changed in the last year and someone could recommend a good profiler please let me know. Cheers. -----Original Message----- From: Caldarale, Charles R [mailto:[EMAIL PROTECTED] Sent: 28 November 2006 18:09 To: Tomcat Users List Subject: RE: Memory leaks on webapp redeploy > From: Mike Quilleash [mailto:[EMAIL PROTECTED] > Subject: RE: Memory leaks on webapp redeploy > > Looks like during the WebappClassLoader cleanup the logging is being > reinitialised. You may well have found the problem. Must be some context-specific logging going on after contextDestroyed() is called. What happens if you put a call to LogFactory.releaseAll() in contextInitialized() rather than contextDestroyed()? This should remove all traces of the prior instance. - Chuck THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY MATERIAL and is thus for use only by the intended recipient. If you received this in error, please contact the sender and delete the e-mail and its attachments from all computers. --------------------------------------------------------------------- To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] This e-mail is bound by the terms and conditions described at http://www.subexazure.com/mail-disclaimer.html --------------------------------------------------------------------- To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]