We are in the process of migrating our application from Websphere to Tomcat. One thing I have noticed is that when I issue the shutdown.sh
for Tomcat, the process still keeps running. Initially I thought the process would end itself in a minute or two, but even after 5 minutes I still see the process alive. So I have to kill the process using kill -9
and then go for a start.
While shutting down I do see a lot of errors getting thrown on the console like:
org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [some_application] appears to have started a thread named [Timer-0] but has failed to stop it.
The code consists of webapps which are made a mix of servlets, spring and a whole bunch of threads are started when the application boots up.
Is there something I can do configuration-wise that would take care of this? Or this needs some code-work to compensate for something that WebSphere provided out-of-the-box?
Issues like that is best handled from code.
Although you can use
catalina.sh stop -force
to terminate the Tomcat instance no matter what, the point here is that Tomcat thinks those threads are running for a reason, and terminating your threads might leave your application in an inconsistent state (if it is terminated halfway of writing something, for example).If you know for a fact that no such thing could happen, use the
-force
switch when stopping Tomcat.However, it is best to write the application to either mark the threads as daemons (by calling
setDaemon(true)
on theThread
instance), so they can be terminated whenever the VM exits, or (if the threads should not be killed at any time) register a shutdown hook by implementingServletContextListener
, and doing the shutdown chores in thecontextDestroyed
method. Here is a question on StackOverflow about installing a shutdown hook.You application is probably leaving a bunch of non-daemon threads running, so it will never shut down.
The thread you mention in your question is a
TimerThread
and Tomcat knows how to shut those down (almost) safely. Just addclearReferencesStopTimerThreads="true"
to your application context:However, as mentioned by Lacek, the proper way to deal with them is through a
ServletContextListener
or another mechanism to administer theThread
's lifecycle. Since you are using a Spring container I would add a TaskScheduler (<task:scheduler id="" pool-size="" />
) to yourApplicationContext
and inject it into every bean that needs scheduling a task. If your servlets need to schedule tasks, create a ScheduledExecutorService in aServletContextListener
and store a reference to it in theServletContext
.PS: there is also a
clearReferencesStopThreads
attribute, but the description in Apache Tomcat Configuration Manual should give you a hint, when to use it: