Tomcat memory leak issue of log4j2 thread

Reetika picture Reetika · Oct 6, 2016 · Viewed 7.3k times · Source

I'm using log4j2 for logging, tomcat8 and java8 version. I used attribute "monitorInterval" to periodically check my log4j2.xml. During shutdown my tomcat i'm facing issue of memory leak.How to resolve this memory leak issue?

Below are the catalina logs:

06-Oct-2016 15:13:55.927 WARNING [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [mywebapp] appears to have started a thread named [Log4j2-Log4j2Scheduled-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: sun.misc.Unsafe.park(Native Method) java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215) java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078) java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093) java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809) java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067) java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127) java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) java.lang.Thread.run(Thread.java:745)

Thanks in advance.

Updated: I analysed my logs, actually logger context is initilising again once Log4jServletContextListener is destroying..

2016-10-22 13:49:36,347 localhost-startStop-2 DEBUG Log4jServletContextListener ensuring that Log4j shuts down properly. 2016-10-22 13:49:36,382 localhost-startStop-2 DEBUG Starting LoggerContext[name=bb4719, org.apache.logging.log4j.core.LoggerContext@d77214]...

Actually in my application i'm using spring ContextLoaderListner in web.xml, so it may using logging internally while destroying spring listner.

Thanks

Answer

Paul Wasilewski picture Paul Wasilewski · Oct 6, 2016

It should work.

Make sure you are including log4j-web in your build.

For example as maven dependency.

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-web</artifactId>
</dependency>

If you are using a servlet 3.0 container or newer (like in Tomcat 8) no additional configuration is necessary (as long as you have not omit Tomcat to scan for ServletContainerInitializer in certain jars). For more information see Using Log4j 2 in Web Applications.


UPDATE

I have trie d it with your set up (Tomcat 8.0.38, Log4j-2.6.2) and it works. To check it if the Log4jServletContextListener and Log4jServletFilter is initialized set the StatusLogger level to DEBUG in your log4j2.xml.

<Configuration monitorInterval="30" status="DEBUG">

After that you should be able to see the follwing outputs in you root logger appender when the app is deployed.

2016-10-14 20:21:36,762 RMI TCP Connection(2)-127.0.0.1 DEBUG Log4jServletContextListener ensuring that Log4j starts up properly.
2016-10-14 20:21:36,764 RMI TCP Connection(2)-127.0.0.1 DEBUG Log4jServletFilter initialized. 

If your app is re-deployed you should see the following lines in your log.

2016-10-14 20:22:00,276 RMI TCP Connection(2)-127.0.0.1 DEBUG Log4jServletFilter destroyed.
2016-10-14 20:22:00,286 RMI TCP Connection(2)-127.0.0.1 DEBUG Log4jServletContextListener ensuring that Log4j shuts down properly.

if you don't see the logs. The you should check your catalina.properties if your jarsToSkip contains any jars of log4j2 or if you have defined a isLog4jAutoInitializationDisabled parameter with the value false in your web.xml.

<context-param>
   <param-name>isLog4jAutoInitializationDisabled</param-name>
   <param-value>false</param-value>
</context-param>