My problem is: each time when I restart my Tomcat as a service (via services.msc in Windows) that process take a long time (about 2 minutes). In Tomcat logs (tomcat9-stderr.yyyy-mm-dd.txt) I see that all threads could not stop properly and, additionaly, there is the issue with unregistration of the JDBC driver:
26-Jul-2024 15:32:16.575 WARNING [Thread-9] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesJdbc The web application [MyWebApp] registered the JDBC driver [net.sourceforge.jtds.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.
26-Jul-2024 15:32:16.575 WARNING [Thread-9] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [MyWebApp] appears to have started a thread named [Timer-0] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
java.lang.Object.wait(Native Method)
java.lang.Object.wait(Unknown Source)
java.util.TimerThread.mainLoop(Unknown Source)
java.util.TimerThread.run(Unknown Source)
The same situation is with each separate thread. So, there are two questions:
I tried to insert the next code inside each thread, but the same exceptions are observed at each restart:
if (Thread.currentThread().isInterrupted())
{
throw new InterruptedException();
}
I use Java 8 and Tomcat-9.
I greatly appreciate any help! Thanks in advance!
No, your own threads are not cleaned up for you, unless you use Jakarta Concurrency.
If you start any executor services, threads, or timers from your Servlet, then you must close those before your web app exits. If you neglect to do this, the backing threads may continue running indefinitely like a zombie 🧟♂️.
You can run code when your web app, your “context”, starts and ends. Write a class that implements ServletContextListener
, and annotate with @WebListener
.
Timer
/TimerTask
Beware: Timer
and TimerTask
were long ago supplanted by the Executors framework added to Java 5, as noted in the Javadoc.
The best solution is to migrate to a Servlet container that supports Jakarta Concurrency rather than open your own executor services, threads, or timers. Such a Servlet container will automatically clean up any threads managed on your behalf.
You have a choice of many such containers including some editions of Apache TomEE (built on top of Tomcat).
Search to learn more. These topics have been covered many times already on Stack Overflow.