Question

I still see this error in tomcat/logs/catalina.out.

Dec 29, 2011 4:04:36 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/LoggingMonitor] appears to have started a thread named [Timer-1] but has failed to stop it. This is very likely to create a memory leak.
Dec 29, 2011 4:04:36 PM org.apache.coyote.http11.Http11Protocol destroy
INFO: Stopping Coyote HTTP/1.1 on http-8180

Is it worth considering and if it is, how can I correct this?

Was it helpful?

Solution

This is probably no big deal (just kill -9 or something) and easy enough to fix. Just figure out which webapp in running on a context of /LoggingMonitor then grep its codebase for...

new Timer();

...and replace them all with...

new Timer( true );

java.util.Timer by default does not run in daemon threads. You need any Timers in your webapps to run on daemon threads (otherwise the container is unable to shutdown properly as it is waiting for the Timer thread to end, which it never does). Find all the "new Timer()" calls and replace them with "new Timer( true )" and the logging complaint should stop.

Spend some time in the JavaDocs learn something about daemon vs non daemon Threads: http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Timer.html

When I'm working in webapps, I always use daemon threads if I end up doing any of my own multithreading. With the facilities in java.util.concurrent, this is becoming very rare (having to do my own Threading stuff).

Finally, and for the record, I hate java.util.Timer and always recommend using something like ScheduledExecutor to do periodic, repetitive tasks. Its too easy to screw up in Timer and take out the Tread it executes on, daemon or otherwise.

OTHER TIPS

That message is not a big deal if you always stop Tomcat when you undeploy/redeploy your app otherwise these operations cause a memory leak that is a big deal, expecially in production.

Threads named "Timer-#" are created by java.util.Timer (and maybe by other classes) as suggested by Bob Kuhar but grepping your own codebase could be not enough and ensuring that you use daemon threads doesn't eliminate that message (the comment by Tom Hawtin is correct).

When I got that message it was produced by a transitive dependency of my code, precisely by class GenericObjectPool of Apache Commons Pool v1.3 that uses a daemon thread (see source code). To find the class that instantiates the Timer I had to put a breackpoint in each Timer class' constructor and then I examined the call stack. To solve the issue I had to upgrade the library (newer versions of Commons Pool don't use that Timer).

When you have control over the code that instantiates the thread you can solve the issue by ensuring that you stop the thread when the application stops. Using daemon threads is a good practice but is not enough because daemon threads die automatically only when you shutdown Tomcat but not when you undeploy the application.

In a more general case, when you have no idea about who created the nasty thread, check Finding Source of Thread Creation in a Java application and Detect Who Created a Thread (w. Eclipse).

UPDATE

A completely different approach is to use the very interesting Leak Prevention Listener. Also read the other posts about classloader leaks by that author.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top