I am preparing a web service for one of my larger projects, using Tomcat, Hibernate and MySQL. While developing I stumbled across several Tomcat error messages that suggest some threads could not be stopped. Most of the threads could simply be vanished by calling Hibernate’s SessionFactory.close() method. However, a few threads seem to remain, e.g.
Jul 09, 2014 10:55:40 AM org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc SEVERE: The web application [/examples] registered the JDBC 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. Jul 09, 2014 10:55:40 AM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads SEVERE: The web application [/examples] appears to have started a thread named [Abandoned connection cleanup thread] but has failed to stop it. This is very likely to create a memory leak. |
and in fact, Tomcat stopped working after a few redeployments due to memory problems. Two main reasons:
- The MySQL AbandonedConnectionCleanupThread does not shutdown correctly.
- The MySQL J/Connector driver doesn’t unregister anymore from the DriverManager.
At least with J/Connector V5.1.31 the problem disappears by using this shutdown procedure (hooked in by a ServletContextListener):
1 2 3 4 5 6 7 8 9 10 11 12 13 | try { com.mysql.jdbc.AbandonedConnectionCleanupThread.shutdown(); } catch (Throwable t) {} // This manually deregisters JDBC driver, which prevents Tomcat 7 from complaining about memory leaks Enumeration<java .sql.Driver> drivers = java.sql.DriverManager.getDrivers(); while (drivers.hasMoreElements()) { java.sql.Driver driver = drivers.nextElement(); try { java.sql.DriverManager.deregisterDriver(driver); } catch (Throwable t) {} } try { Thread.sleep(2000L); } catch (Exception e) {} </java> |
I still have to observe long-term effects and will keep you informed.