commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Simon Kitching <skitch...@apache.org>
Subject Re: [logging] lon4j only implementation to solve out of memory errors
Date Wed, 27 Jul 2005 08:19:49 GMT
On Tue, 2005-07-26 at 08:09 -0700, Paul Austin wrote:
> Hi Simon,
> 
> I am running my application on Tomcat 5.5 under Sun JDK 1.4.2_07-b05
> on Windows XP. For the production environment it will be Oracle
> Application Server 9.0.4.1 under JDK 1.4.2 on Solaris 2.8 (I haven't
> had access to test on that server yet).
> 
> The original discussion where I started to find out about the problem
> was on the hibernate forums.
> 
> http://forum.hibernate.org/viewtopic.php?t=935948&highlight=permgen

Hmm. I wish people would stop trying to push libraries that are
component-specific up into the container's lib directories. Component
libs belong in the component. SLAP. Component libs belong in the
component SLAP. Repeat as necessary. Note that this doesn't apply to
Tomcat's inclusion of JCL in the container - JCL is *part* of tomcat,
and JCL explicitly calls LogFactory.release when unloading webapps so
the problem doesn't occur there.

Unfortunately Sun's standard libs provide no way to implement a clean
workaround when people insist on deploying JCL in the container. The
components in a container are meant to be "scoped" by their context
classloader - but there is *absolutely no way* to attach arbitrary data
to the classloader so that when the classloader is dropped that data is
also recycled. Well, except by ensuring the data is stored as static
fields on a class loaded by that context classloader. But people insist
on not doing that and pushing the JCL libs up into the container's lib
directories. SLAP.

The closest approximation to a solution is to have a map keyed by
context classloader but that requires people to then explicitly release
the map entry when the webapp is unloaded.


> One of the things I tried was adding a context listener which had the
> LogFactory.release method called. There are also 3 filters which use
> springframework/hibernate which use libraries that may use
> commons-logging. I'm guessing that perhaps the destroy method on the
> filters is called after I call LogFactory.release thus some new log
> instances are created thus undoing the work in the release method.

Hmm.. that might be possible. 

> 
> I'll try to get a stripped down copy of the application that still has
> the issue put together to help solve this problem. Won't be this week
> as I have to deliver the application.

There is one other thing worth trying. It has occurred to me that if
there are multiple copies of LogFactory lying around then maybe in some
cases release needs to be called on each copy not just one.

You could try putting this in the ServletContextListener's destroy
method:
    Class[] releaseSig = new Class[] {ClassLoader.class};
    ClassLoader c = Thread.currentThread().getContextClassLoader();
    Object[] releaseParams = new Object[1];
    releaseParams[0] = c;
    while (c != null) {
        Class lf = c.loadClass(LogFactory.class.getName());
        if (lf != null) {
            try {
                Method m = lf.getMethod("release", releaseSig);
                m.invoke(releaseParams);
            } catch(Exception e) {
                // ignore
            }
        }
        c = c.getParent();
    }

Note that the above code hasn't been tested (it might not even compile)

Regards,

Simon


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-user-help@jakarta.apache.org


Mime
View raw message