Tomcat中Web应用程序停止时为了防止内存泄漏,JDBC驱动程序被强制取消注册出现原因

发布于:2025-05-07 ⋅ 阅读:(18) ⋅ 点赞:(0)

1.问题描述

本地Windows环境开发的Springboot项目同样的mysql版本,jdk版本,tomcat版本,本地运行没有任何问题,发布到阿里云服务器上时报以下问题:

06-May-2025 20:06:12.842 警告 [main] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesJdbc Web应用程序 [xxxxx-admin] 注册了JDBC驱动程序 [com.alibaba.druid.proxy.DruidDriver],但在Web应用程序停止时无法注销它。 为防止内存泄漏,JDBC驱动程序已被强制取消注册。
06-May-2025 20:06:12.842 警告 [main] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesJdbc Web应用程序 [xxxxx-admin] 注册了JDBC驱动程序 [com.mysql.jdbc.Driver],但在Web应用程序停止时无法注销它。 为防止内存泄漏,JDBC驱动程序已被强制取消注册。
06-May-2025 20:06:12.852 警告 [main] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads Web应用程序[xxxxx-admin]似乎启动了一个名为[crmeb-scheduled-task-pool-1]的线程,但未能停止它。这很可能会造成内存泄漏。线程的堆栈跟踪:[
 sun.misc.Unsafe.park(Native Method)
 java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
 java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1088)
 java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
 java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
 java.lang.Thread.run(Thread.java:748)]

以上异常信息,上网查找了很多,终于成功解决。

解决办法:

手动配置监听器,用来在Tomcat关闭时取消注册JDBC驱动程序,并将线程停止

编写自定义监听器

代码如下:

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

//mysql8及以上用 com.mysql.cj

import com.mysql.jdbc.AbandonedConnectionCleanupThread;
//import com.mysql.cj.jdbc.AbandonedConnectionCleanupThread;

import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;

@WebListener
public class DriverMangerListener implements ServletContextListener {

    public void contextInitialized(ServletContextEvent sce) {
    }

    public void contextDestroyed(ServletContextEvent sce) {
        AbandonedConnectionCleanupThread.uncheckedShutdown();
        Enumeration<Driver> enumeration = DriverManager.getDrivers();
        while (enumeration.hasMoreElements()) {
            try {
                DriverManager.deregisterDriver(enumeration.nextElement());
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

我的是Springboot项目直接用@WebListener注解即可,要是ssm或者springmvc项目的话,在web.xml中添加以下代码注册该listener即可,注意类的路径以及该配置所在文件中的位置。

<listener>
     <listener-class>com.ssm.util.DriverMangerListener</listener-class>
</listener>

 


网站公告

今日签到

点亮在社区的每一天
去签到