SSM框架 Tomcat 停止时 JAVA进程未停止 的解决方法

SSM框架结束时报错如下:
SSM框架报错
这会导致Tomcat 服务器停止后Java进程尚未停止, 继续占用内存, 必须通过 类似 kill -9 之类的命令去杀死java进程.

这是由于在服务器停止时有些线程尚未销毁所引起的, 如ThreadLocal; Scheduler 启动的线程; JDBC driver等.

解决办法:
自定义ContextLoaderListener,在项目结束时关闭他们:

/**
 * 自定义的ContestLoaderListener
 * 监听servletContext创建和消亡,即web应用的开始和结束时执行
 * 本类继承自SpringMVC的ContextLoaderListener
 * 在执行本类方法前首先执行父类方法
 * <p>
 * 需要配置本类在 web.xml 文件中:
 * <listener>
 * <listener-class>com.qinghe.MyContextLoaderListener</listener-class>
 * </listener>
 * <p>
 * auther:XingTL
 * date:2020/6/20 17:46
 */
public class MyContextLoaderListener extends ContextLoaderListener {
    private static final Logger logger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger("com.qinghe.MyContextLoaderListener");

    /**
     * 当Servlet 容器启动Web 应用时调用该方法。
     * 在调用完该方法之后,容器再对Filter 初始化,
     * 并且对那些在Web 应用启动时就需要被初始化的Servlet 进行初始化。
     *
     * @param sce servletContext 初始化事件 即web应用开始
     */
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        super.contextInitialized(sce);
    }

    //实现其中的销毁函数
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        super.contextDestroyed(sce);
        //销毁线程等
        destroyJDBCDrivers();
        destroySpecifyThreads();
    }

    private void destroySpecifyThreads() {
        final Set<Thread> threads = Thread.getAllStackTraces().keySet();
        for (Thread thread : threads) {
            if (needManualDestroy(thread)) {
                synchronized (this) {
                    try {
                        thread.stop();
                        logger.debug(String.format("Destroy  %s successful", thread));
                    } catch (Exception e) {
                        logger.warn(String.format("Destroy %s error", thread), e);
                    }
                }
            }
        }
    }
	//该数组中即为报错的未结束的线程名
    private final String[] MANUAL_DESTROY_THREAD_IDENTIFIERS = {
            "Timer-0",
            "com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0",
            "com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#1",
            "com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2",
    };

    private boolean needManualDestroy(Thread thread) {
        final String threadName = thread.getName();
        for (String manualDestroyThreadIdentifier : MANUAL_DESTROY_THREAD_IDENTIFIERS) {
            if (threadName.contains(manualDestroyThreadIdentifier)) {
                return true;
            }
        }
        return false;
    }

    private void destroyJDBCDrivers() {
        final Enumeration<Driver> drivers = DriverManager.getDrivers();
        Driver driver;
        while (drivers.hasMoreElements()) {
            driver = drivers.nextElement();
            try {
                DriverManager.deregisterDriver(driver);
                logger.debug(String.format("Deregister JDBC driver %s successful", driver));
            } catch (SQLException e) {
                logger.warn(String.format("Deregister JDBC driver %s error", driver), e);
            }
        }
    }
}

问题解决

本文参考:https://blog.csdn.net/monkeyking1987/article/details/9182201

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值