这是异常信息。本人使用的mysql8.0数据库驱动版本mysql-connector-java Version 8.0.11,发生这种情况的原因主要是Dbcp2的XBasicDataSource在关闭连接池的时候没有正确地关闭连接池之前容器就被摧毁了导致的。
The web application [xxxxx] 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. Stack trace of thread: java.lang.Object.wait(Native Method) java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143) com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:70) java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) java.lang.Thread.run(Thread.java:748) 13-May-2018 00:02:01.387 INFO [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["http-nio-8082"] 13-May-2018 00:02:01.392 INFO [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["ajp-nio-8010"] 13-May-2018 00:02:01.397 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["http-nio-8082"] 13-May-2018 00:02:01.398 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["ajp-nio-8010"]
这时候需要加入一个监听器重写一下BasicDataSource的close方法调用DriverManager.deregisterDriver()这个方法去注销掉数据库的链接,
然后使用数据库驱动包的AbandonedConnectionCleanupThread.checkedShutdown()这个方法去安全注销线程
package cn.devil.configs; import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Enumeration; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; import org.apache.commons.dbcp2.BasicDataSource; import com.mysql.cj.jdbc.AbandonedConnectionCleanupThread; @WebListener public class MvcLissener extends BasicDataSource implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent servletContextEvent) { } @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { //这里如果Web应用拥有多个数据库的连接,可以一并关闭 Enumeration<Driver> drivers = DriverManager.getDrivers(); Driver driver = null; while (drivers.hasMoreElements()) { try { driver = drivers.nextElement(); DriverManager.deregisterDriver(driver); } catch (SQLException ex) { } } AbandonedConnectionCleanupThread.checkedShutdown(); } @Override public synchronized void close() throws SQLException { // 以下两句代码分别对应两个资源的关闭 DriverManager.deregisterDriver(DriverManager.getDriver(getUrl())); AbandonedConnectionCleanupThread.checkedShutdown(); super.close(); } }
但是之后又发生了一个问题,程序报驱动不匹配的异常,我仔细检查了驱动driverClassName的配置并没有问题URL也没有问题。于是就手动调用DriverManager获取驱动地址
正常注销掉。程序就一切正常了。