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> 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)