Tomcat 6 memory leaks log entries
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 adddestroy-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 callFileCleaningTracker.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 byExecutors
utility insideExecutorService
. Make sure you callshutdown()
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 settingSchedulerFactoryBean.waitForJobsToCompleteOnShutdown
totrue
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.
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; }}
Shutdown your webapp properly. Don't leave these threads running.
Alternatively, don't keep redeploying the webapp.