Volodymyr Siedlecki created BEANUTILS-566:
---------------------------------------------

             Summary: Classloader Out-Of-Memory Error: Server-Provided 
BeanUtils and Application-Provided Logger
                 Key: BEANUTILS-566
                 URL: https://issues.apache.org/jira/browse/BEANUTILS-566
             Project: Commons BeanUtils
          Issue Type: Bug
    Affects Versions: 1.9.4
            Reporter: Volodymyr Siedlecki


Hello,

We have a classloader leak occurring in WebSphere.  The server provides 
BeanUtils (used by JSF) while the application provides it's own Logger (SLF4J). 
This configuration causes eventually causes a leak. We've tried other ways to 
solve this leak, but the only working solution has been to update the BeanUtil 
code. 

*Explanation of the leak:*

In a server-level class (in this case, BeanUtilsBean) has a reference to a 
class loaded by an application class loader (SLF4JLocationAwareLog). This is 
generally fine... until the application is stopped. When the application stops, 
its class loader is "disposed" (we clear out its internal class path and some 
other references) and ideally should be eligible for garbage collection, but 
the reference to one of its classes prevents that. The chain below shows 
BeanUtilsBean -> SLF4JLocationAwareLog -> SLF4JLocationAwareLog's class loader 
(the CompoundClassLoader), and that class loader cannot be GC'd unless the 
reference to that application copy of SLF4JLocationAwareLog is cleared.

 
{code:java}
com.ibm.ws.classloader.CompoundClassLoader @ 0x9a708520 war:CustomerApp/App.war
'- <classloader>, <classLoader> class 
org.apache.commons.logging.impl.SLF4JLocationAwareLog @ 0xb0074658
'- <class&gt; org.apache.commons.logging.impl.SLF4JLocationAwareLog @ 0xb15557e8
'- log org.apache.commons.beanutils.BeanUtilsBean @ 0xb1538560
'- value java.util.WeakHashMap$Entry @ 0xb1537e78 war:CustomerApp/App.war
{code}

*Proposed Fix:*
By using the context class loader for logger instantiation, this leak can be 
easily resolved via the code below. (albeit applied to every logger instance).  
 Perhaps it could be hidden behind a JVM property, if applied?

 
{code:java}
private final Log log = getLoggerWithCorrectClassLoader();public Log 
getLoggerWithContextClassLoader() {
    java.lang.ClassLoader currentCL = 
Thread.currentThread().getContextClassLoader();
    Log log = null;
    try {
      
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
      log = LogFactory.getLog(getClass());
    } finally {
      Thread.currentThread().setContextClassLoader(currentCL);
    }
    return log;
}{code}
 

I see there are other issues open relating to updating the loggers 
–https://issues.apache.org/jira/browse/BEANUTILS-562

Perhaps this could also be considered. Thanks! 

 



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to