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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19189312/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 14:54:21  来源:igfitidea点击:

JDBC Driver has been forcibly unregistered by Tomcat 7, why?

javatomcatjdbc

提问by AAH

I have a problem in tomcat 7, and here are some info about it,

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

1 - I have this message:

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 - When I reload the application the problem solved for about 20 hours then comes back again.

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

3 - I have about 10 application deployed on the tomcat but just 2 of them gets this error.

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

4 - the problem was not exist from the begging with these 2 apps but appeared from about 2 weeks.

4 - 乞求这两个应用程序时不存在问题,但出现了大约 2 周。

So how can I solve this and is it related to my code?

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

回答by Sotirios Delimanolis

When you stop a web application in Tomcat, it tries to shutdown the threads it started and closes a bunch of resources, for example the JDBC drivers. Although in this case it is capable of closing them, it's safer to do it yourself.

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

You can do this in a ServletContextListener. I've implemented mine as follows

您可以在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 does starts a Thread that Tomcat cannot close. For current versions (5.1.23+), they've provided the AbandonedConnectionCleanupThreadclass to close the spawned Thread, as you can see above.

MySQL 确实启动了一个 Tomcat 无法关闭的线程。对于当前版本 (5.1.23+),他们提供了AbandonedConnectionCleanupThread关闭spawned 的类Thread,如上所示。

回答by Christopher Schultz

If you have your Connector/J JDBC driver in each webapp's WEB-INF/libdirectory, then you will likely have similar problems with all of your webapps -- not just this one.

如果您在每个 web 应用程序的WEB-INF/lib目录中都有连接器/J JDBC 驱动程序,那么您的所有 web 应用程序可能都会遇到类似的问题——而不仅仅是这个。

If you are using Tomcat's JDBC connection pool, then you should put the Connector/J driver into Tomcat's lib/directory and remove it from all of your webapps. If you are maintaining your own connection pool from within your own application, then you will have to arrange for the JDBC driver to be de-register itself with the global DriverManager. Better yet, use Connector/J's non-registering driver instead of the registering driver and then you don't have to worry about these kinds of leaks that Tomcat is actually protecting you from.

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