最近一个同学的项目在打包部署tomcat后报错如下:
[mysql-cj-abandoned-connection-cleanup] org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading 非法访问:此Web应用程序实例已停止。无法加载[]。为了调试以及终止导致非法访问的线程,将抛出以下堆栈跟踪。
java.lang.IllegalStateException: 非法访问:此Web应用程序实例已停止。无法加载[]。为了调试以及终止导致非法访问的线程,将抛出以下堆栈跟踪。
at org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading(WebappClassLoaderBase.java:1440)
at org.apache.catalina.loader.WebappClassLoaderBase.getResource(WebappClassLoaderBase.java:1065)
at com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.checkThreadContextClassLoader(AbandonedConnectionCleanupThread.java:117)
at com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:84)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
java.lang.IllegalStateException: 非法访问:此Web应用程序实例已停止。无法加载[]。为了调试以及终止导致非法访问的线程,将抛出以下堆栈跟踪。
at org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading(WebappClassLoaderBase.java:1440)
at org.apache.catalina.loader.WebappClassLoaderBase.getResource(WebappClassLoaderBase.java:1065)
at com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.checkThreadContextClassLoader(AbandonedConnectionCleanupThread.java:117)
at com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:84)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
具体类似如图:
一开始以为这个错是因为打war包出现的问题,因为项目本身在idea开发工具中是能正常启动运行,一点错没有,只是通过maven打成war包部署到云服务器上的tomcat中,一启动到最后就报如上错误,那么这个问题该如何解决呢?
解决方案
先说下网上一种方案,潘老师也试过但好像没用,但还是说明下:
网上这种解决方案是在tomcat的servel.xml
的Context
标签中加个reloadable="false"
属性,其实默认配置里好像没有这个标签,可能用eclispe部署或者idea部署进去才会有,我自己手工加了这个标签,没有能解决问题。
下面是重点,通过如下方法,确实解决了该问题,只需如下操作即可:
我们在项目中新建一个名为ContextFinalizer
的监听类,具体代码如下:
package com.panziye.listener; import com.mysql.cj.jdbc.AbandonedConnectionCleanupThread; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Enumeration; @WebListener public class ContextFinalizer implements ServletContextListener{ public void contextInitialized(ServletContextEvent sce) {} public void contextDestroyed(ServletContextEvent sce) { Enumeration<Driver> drivers = DriverManager.getDrivers(); Driver d = null; while (drivers.hasMoreElements()) { try { d = drivers.nextElement(); DriverManager.deregisterDriver(d); } catch (SQLException ex) { } } try { // 注意:mysql8版本的jar好像shutdown方法私有了,只能调用checkedShutdown或uncheckedShutdown AbandonedConnectionCleanupThread.checkedShutdown(); } catch (InterruptedException e) { e.printStackTrace(); } } }
提示:
@WebListener
这个注解相当于在web.xml
配置如下内容
<listener> <listener-class> com.panziye.listener.ContextFinalizer </listener-class> </listener>
然后我们再去打包部署,运行tocmat,发现就不报错了,mysql-cj-abandoned-connection-cleanup非法访问:此Web应用程序实例已停止的问题成功解决。