tomcat-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Mike Quilleash " <mike.quille...@subexazure.com>
Subject RE: Memory leaks on webapp redeploy
Date Tue, 28 Nov 2006 18:57:22 GMT
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:Chuck.Caldarale@unisys.com] 
Sent: 28 November 2006 18:09
To: Tomcat Users List
Subject: RE: Memory leaks on webapp redeploy

> From: Mike Quilleash [mailto:mike.quilleash@subexazure.com]
> 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: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org



 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: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Mime
View raw message