[
https://issues.apache.org/jira/browse/LOG4J2-819?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14132571#comment-14132571
]
Remko Popma edited comment on LOG4J2-819 at 9/13/14 8:09 AM:
-------------------------------------------------------------
Costa, thanks for helping with the investigation.
I think this is caused by Tomcat trying to prevent memory leaks. (Ironic isn't
it?)
http://wiki.apache.org/tomcat/MemoryLeakProtection#staticClassVariables
{quote}
When an app is stopped, Tomcat (even before 6.0.24) nullifies the value of all
static class variables of classes loaded by the WebAppClassLoader.
{quote}
So Tomcat, bless its little white cotton socks, causes the very problem it is
trying to prevent: referencing the static fields in CachedClock and
CoarseCachedClock will initialize these classes, which starts the background
threads. Once these threads are started, the web app cannot be unloaded
anymore, and voila, we have a memory leak.
I'm sure we are not the first to have this problem because Tomcat provides a
workaround. They suggest to configure a [JRE Memory Leak Prevention
Listener|http://tomcat.apache.org/tomcat-6.0-doc/config/listeners.html#JRE_Memory_Leak_Prevention_Listener_-_org.apache.catalina.core.JreMemoryLeakPreventionListener].
This supports a {{classesToInitialize}} attribute where we can specify the
classes that should be loaded by Tomcat's common class loader instead of the
webapp's context class loader.
I tried this, but unfortunately this initialization takes place at Tomcat
startup, and with the log4j-core jar inside the demo.war file and not in
Tomcat's lib folder I got a JreMemoryLeakPreventionListener
ClassNotFoundException "Failed to load class
org.apache.logging.log4j.core.util.CachedClock during Tomcat start to prevent
possible memory leaks". So the workaround does not work for us here.
Potential solutions:
* Modify ClockFactory so that the CachedClock and CoarseCachedClock classes are
not loaded unless the user explicitly requests these clocks, using reflection
in ClockFactory.
* Remove CachedClock and CoarseCachedClock from log4j-core altogether.
* A stop() mechanism will not help because there is nobody around to call it
(the web app has already been stopped before these threads are started by
Tomcat's cleanup)
Although I suggested it, I'm still a bit on the fence about removing these
classes. Remember that
[benchmarks|https://issues.apache.org/jira/browse/LOG4J2-744?focusedCommentId=14077425&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-14077425]
showed that System.currentTimeMillis() can take 3+ microseconds on Linux, vs
14 nanoseconds on Windows: a 220x(!) difference...
Thoughts?
was (Author: [email protected]):
Costa, thanks for helping with the investigation.
I think this is caused by Tomcat trying to prevent memory leaks. (Ironic isn't
it?)
http://wiki.apache.org/tomcat/MemoryLeakProtection#staticClassVariables
{quote}
When an app is stopped, Tomcat (even before 6.0.24) nullifies the value of all
static class variables of classes loaded by the WebAppClassLoader.
{quote}
> PermGen OutOfMemoryError when reloading webapp on Tomcat 6
> ----------------------------------------------------------
>
> Key: LOG4J2-819
> URL: https://issues.apache.org/jira/browse/LOG4J2-819
> Project: Log4j 2
> Issue Type: Bug
> Components: Core
> Affects Versions: 2.0.2
> Environment: Tomcat 6
> Reporter: Costa Theodosiou
> Priority: Critical
> Attachments: demo.zip, demorun-tomcat6-with-reload.zip, demorun.zip,
> gg-log4j2-clocks-interrupts.patch, gg-log4j2-clocks-v2.patch
>
>
> When reloading an application 3 or 4 times in Tomcat 6, the application
> crashes with a "java.lang.OutOfMemoryError: PermGen space" exception.
> After some investigation using the "When all else fails" section of
> https://wiki.apache.org/tomcat/OutOfMemory in conjunction with Java VisualVM,
> I have narrowed down the problem to the Thread created within
> org.apache.logging.log4j.core.util.CoarseCachedClock.
> When a Thread is created, it contains a reference to the classloader that it
> was created with. In this case, the Thread's contextClassLoader field
> contains a reference to the WebappClassLoader. When Tomcat attempts to unload
> the webapp, the Thread still holds onto this reference which prevents
> WebappClassLoader from being freed.
> Perhaps the Log4jServletContextListener (Log4jWebInitializerImpl) can be made
> to stop the CoarseCachedClock thread.
> I believe this is not an obvious issue on Tomcat 7 due to
> https://wiki.apache.org/tomcat/MemoryLeakProtection.
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]