commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From David Perez <craquer...@yahoo.es>
Subject Re: Commons logging and memory leaks
Date Thu, 19 May 2005 07:19:28 GMT
Thanks Simon,

Simon Kitching schrieb:

>On Wed, 2005-05-18 at 12:20 +0200, David Perez wrote:
>  
>
>>You're right, I have changed the commons-logging version to the latest one.
>>Now I have reverted to commons-logging-1.0.2
>>    
>>
>
>I would recommend using commons-logging-1.0.4. After all, that is the
>most recent official release.
>
>  
>
I have already done so successfully.  See below for more details.

>  
>
>>>I suggest registering a ServletContextListener. Declare a <listener>
>>>element in the web.xml file, with a nested <listener-class> element
>>>containing the fully qualified classname of a logging-cleanup class. In
>>>the contextDestroyed method of that class do this:
>>>* LogFactory.release(
>>>    Thread.currentThread().getContextClassLoader())
>>>* somehow cleaning up the underlying logging library if needed.
>>>
>>>If that doesn't help, let me know and we can look into it a bit
>>>further. 
>>> 
>>>
>>>      
>>>
>> From my code I call LogFactory.releaseAll() after removing the old web 
>>app context, and no luck :-(
>>    
>>
>
>Do you mean that you use a ServletContextListener as I described? Or
>something else?
>
>Note also that LogFactory.releaseAll may not do what you want. If your
>webapp has bound to commons-logging that is loaded via a shared
>classloader, then calling releaseAll will shut down *all* instances of
>commons-logging - which other webapps running in the same container may
>not appreciate :-). The code I recommended will only shut down logging
>for the webapp whose context is being destroyed, assuming you are
>calling the method from a SerletContextListener.contextDestroyed, ie
>from code where Thread.currentThread.getContextClassLoader() returns the
>classloader of the webapp being unloaded.
>
>  
>
Now I use LogFactory.release()

>>Should my webapp use another copy of commons-logging.jar?
>>    
>>
>
>That depends.
>
>If your webapp has all the libraries it needs in WEB-INF/lib, then yes.
>Deploying commons-logging.jar in WEB-INF/lib in that situation makes
>things very clean and consistent. There's no need to use call
>LogFactory.release() in this case, as undeploying the webapp
>automatically undeploys commons-logging and the underlying logging lib.
>
>But if your webapp is calling into code that is deployed via a shared
>classloader, and that code uses commons-logging, then you must *not*
>also deploy commons-logging in WEB-INF/lib. If you do (and you are using
>release 1.0.4), you will get the message
>  Invalid class loader hierarchy.  
>  You have more than one version of org.apache.commons.logging.Log
>  visible, which is not allowed.
>If you are using an earlier release, you will probably get something
>like:
>  AvalonLogger does not implement Log
>
>
>  
>
Finally I use a shared instance.

>  
>
>>Here is the logging jars I use in my app:
>>
>>jars used by the web server (Jetty):
>>
>>    * commons-logging.jar and
>>    * log4j.jar
>>
>>jars used by the webapp:
>>
>>    *    logkit.jar
>>
>>    My web app uses Cocoon which uses Avalon LogKit, and makes me 
>>include logkit.jar, even though logging is redirected to log4j. 
>>    
>>
>
>What do you mean "logging is redirected to log4j"?
>
>  
>
Avalon LogKit can be configured to use the Log4J subsystem.  I like more 
Log4J than Avalon LogKit.

>>    Some other classes use directly commons-logging
>>
>>With commons-logging-1.0.4 and 1.05 alpha1, I have to make logkit.jar 
>>available to Jetty, otherwise commons-loggings throws a 
>>ClassNotFoundException, because it cannot find
>>
>>org/apache/log/Hierarchy.  I wonder why it tries to load LogKit if Log4j is already
available?
>>    
>>
>
>Commons-logging does *not* auto-discover LogKit; it doesn't even try. So
>somewhere something in your webapp must be *ordering* commons-logging to
>use AvalonLogger (aka LogKit) as the logger. 
>
>Which logging lib commons-logging uses can be explicitly set via a
>number of methods; .properties files, jdk1.3 service files, system
>properties. See the commons-logging documentation for more information.
>
>  
>
You were right, I had a WEB-INF/classes/common-logging.properties file,  
of my webapp, that I used to use before I decided to use log4j instead 
of LogKit. 
Commons-loggind 1.02 did ignore this file, but version 1.0.4 didn't. 
This what has confused me.

>  
>
>>Caused by: java.lang.NoClassDefFoundError: org/apache/log/Hierarchy
>>	at org.apache.commons.logging.impl.LogKitLogger.getLogger(LogKitLogger.java:77)
>>	at org.apache.commons.logging.impl.LogKitLogger.<init>(LogKitLogger.java:64)
>>	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
>>	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
>>	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
>>	at java.lang.reflect.Constructor.newInstance(Constructor.java:494)
>>	at org.apache.commons.logging.impl.LogFactoryImpl.newInstance(LogFactoryImpl.java:529)
>>    
>>
>
>Yep, commons-logging's LogFactoryImpl is explicitly trying to
>instantiate a LogKitLogger object. 
>
>
>
>Can you please:
>(a) look for what is ordering commons-logging to use LogKit and remove
>that?
>(b) use commons-logging 1.0.4; I will be able to help you much better
>than if you use the very old 1.0.2. 
>
>Also, can you please confirm that Jetty (and your webapp) use the
>standard child-first (aka parent-last) classloading order? I know the
>Resin webserver doesn't, and that makes things quite different...
>
>
>And by the way, where do you put your log4j configuration file? 
>
>
>  
>
I load it programmatically with a call to
    PropertyConfigurator.configureAndWatch(new File(basedir, 
"logs/"+System.getProperty("loggging.file", 
"log-production.properties")).toString());
in this way I can

   1. change dynamically the logging configuration
   2. have two sets of logging configurations: one for production (the
      default) and other for development (overriden through a system
      property in the debug launch). In this way, increasing log level
      for testing purposes never goes to production inadvertently.

>Good luck!
>  
>
Now I have only problems with log4j and some other static instances, but 
not with commons-logging!!
Thanks for your invaluable help.

David

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message