JDBC Driver被Tomcat 7强行注销了,为什么?

2022-09-03 01:07:52

我在tomcat 7中有一个问题,这里有一些关于它的信息,

1 - 我有这个消息:

INFO: Reloading Context with name [/WebApp] has started
Oct 04, 2013 12:20:50 PM org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc
SEVERE: The web application [/WebApp] 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.

Oct 04, 2013 12:20:50 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/WebApp] 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.
Oct 04, 2013 12:20:51 PM org.apache.catalina.core.StandardContext reload
INFO: Reloading Context with name [/WebApp] is completed

2 - 当我重新加载应用程序时,问题解决了大约20个小时,然后又回来了。

3 - 我在tomcat上部署了大约10个应用程序,但其中只有2个得到了这个错误。

4 - 问题不存在于这2个应用程序的乞讨中,而是从大约2周开始出现。

那么我该如何解决这个问题,它与我的代码有关吗?


答案 1

当您在Tomcat中停止Web应用程序时,它会尝试关闭它启动的线程并关闭一堆资源,例如JDBC驱动程序。尽管在这种情况下,它能够关闭它们,但自己做更安全。

您可以在 .我已经实现了我的如下ServletContextListener

@WebListener // register it as you wish
public class ContainerContextClosedHandler implements ServletContextListener {
    private static final Logger logger = LoggerFactory.getLogger(ContainerContextClosedHandler.class);

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        // nothing to do
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        Enumeration<Driver> drivers = DriverManager.getDrivers();     

        Driver driver = null;

        // clear drivers
        while(drivers.hasMoreElements()) {
            try {
                driver = drivers.nextElement();
                DriverManager.deregisterDriver(driver);

            } catch (SQLException ex) {
                // deregistration failed, might want to do something, log at the very least
            }
        }

        // MySQL driver leaves around a thread. This static method cleans it up.
        try {
            AbandonedConnectionCleanupThread.shutdown();
        } catch (InterruptedException e) {
            // again failure, not much you can do
        }
    }

}

MySQL确实启动了Tomcat无法关闭的线程。对于当前版本(5.1.23 +),他们提供了该类来关闭生成的 ,如上所示。AbandonedConnectionCleanupThreadThread


答案 2

如果每个 Web 应用的目录中都有 Connector/J JDBC 驱动程序,则所有 Web 应用都可能遇到类似的问题,而不仅仅是这个。WEB-INF/lib

如果您使用的是 Tomcat 的 JDBC 连接池,则应将 Connector/J 驱动程序放入 Tomcat 的目录中,并将其从所有 Web 应用程序中删除。如果要从自己的应用程序中维护自己的连接池,则必须安排 JDBC 驱动程序在全局 中自行取消注册。更好的是,使用 Connector/J 的非注册驱动程序而不是注册驱动程序,然后您不必担心 Tomcat 实际上正在保护您免受此类泄漏。lib/DriverManager


推荐