Tomcat 6 memory leaks log entries

23k views Asked by At

Below is outtake of unique entries in my Catalina.out file on CentOS machine. I'm running Tomcat 6 with spring 3 and my application. There is whole bunch of them so I just picked some that keep repeating. This doesn't happen all the time but it happens at least once a week.

The Question is what can I do to prevent the bellow from happening?

Feb 3, 2011 2:37:48 PM org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc

SEVERE: The web application [] registered the JBDC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.

Feb 3, 2011 2:37:48 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads

SEVERE: The web application [] appears to have started a thread named [com.iteezy.shared.domain.DirEntry.data] but has failed to stop it. This is very likely to create a memory leak.


Feb 3, 2011 2:37:48 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [] appears to have started a thread named

[com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0] but has failed to stop it. This is very likely to create a memory leak.


Feb 3, 2011 2:37:48 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads  

SEVERE: The web application [] appears to have started a thread named [File Reaper] but has failed to stop it. This is very likely to create a memory leak.

Feb 3, 2011 2:37:48 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads

SEVERE: The web application [] appears to have started a thread named [pool-1-thread-22] but has failed to stop it. This is very likely to create a memory leak.  

37:48 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
b application [] appears to have started a thread named 

[org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2] but has failed to stop it. This is very likely to create a memory leak.

37:48 PM org.apache.catalina.loader.WebappClassLoader clearThreadLocalMap

b application [] created a ThreadLocal with key of type [net.sf.json.AbstractJSON$1] (value [net.sf.json.AbstractJSON$1@40bbb3d6]) and a value of type [java.util.HashSet] (value [[]]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
3

There are 3 answers

0
Tomasz Nurkiewicz On BEST ANSWER

When you define an external flag which a thread is suppose to poll and exit when it's set - it must be volatile. Otherwise the thread might never see the change made by other thread.

However there is already a feature like that in standard API - it is called an interrupt() method and Thread.currentThread().isInterrupted(). No need to duplicate already existing logic. See: Stopping a specific java thread.

That being said calling interrupt() on each and every thread is a bad idea as well because there is no guarantee that all threads respond to it. Examining your exceptions I noticed the following threads not being cleaned up properly:

  • com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0 - close the C3P0 data source. Since you are using Spring simply add destroy-method="close". We're done with this thread.

  • File Reaper - as far as I can see this thread is created by FileCleaningTracker. You need to call FileCleaningTracker.exitWhenFinished() explicitly when shutting down your application (or when the class is no longer needed, I never used it) or let Spring to do this (see above). Chances are some 3rd party library uses it and not closing properly - this means it has a bug.

  • pool-1-thread-22 - this is one of the threads created by Executors utility inside ExecutorService. Make sure you call shutdown() on every such a pool in your application during shutdown.

  • org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2 - Quartz worker thread (the one that actually runs jobs). SchedulerFactoryBean closes the scheduler for you automatically, I think Tomcat is mistaken here, I see this error often as well. Nevertheless looks like setting SchedulerFactoryBean.waitForJobsToCompleteOnShutdown to true solves this.

  • com.iteezy.shared.domain.DirEntry.data - I am not sure about this one. It is either your own thread that needs to be interrupted upon shutdown or H2 database thread (?) Its stack needs to be examined to guess where does it come from.

The bottom line is: don't just kill everything that moves (actually, Tomcat does that for you after issuing this warning) but determine where the threads come from and use framework/library specific close() method to allow further cleanup. Be gentle.

1
OrangeDog On

Shutdown your webapp properly. Don't leave these threads running.

Alternatively, don't keep redeploying the webapp.

3
Rich On

Set up a Servlet to manage this in its destroy() method. The threads can check a flag to see if they must continue or not.

In your servlet, do the following in the destroy method. You will obviously need to be able to have access to a Collection<MyThread> but how you get that really depends on how your system is set up.

destroy() {
    for (MyThread thread : myThreads) {
        thread.stopProcessing();
    }
}

Your MyThread class will have something like this:

public class MyThread {
    private boolean finished = false;

    @Override
    public void run() {
        while (!finished) {
            //do something
        }
    }

    public void stopProcessing() {
        finished = true;
    }
}