为了账号安全,请及时绑定邮箱和手机立即绑定

为了防止内存泄漏,jdbc驱动程序已强制取消注册。

为了防止内存泄漏,jdbc驱动程序已强制取消注册。

尚方宝剑之说 2019-06-18 10:32:10
为了防止内存泄漏,jdbc驱动程序已强制取消注册。当我运行我的web应用程序时,我会收到这条消息。它运行的很好,但我在关机期间收到了这条消息。严重:Web应用程序注册了JBDC驱动程序[oracle.jdbc.driver.OracleDriver],但在Web应用程序停止时未能将其注销。为了防止内存泄漏,JDBC驱动程序被强制取消注册。任何帮助都很感激。
查看完整描述

3 回答

?
凤凰求蛊

TA贡献1825条经验 获得超4个赞

自6.0.24版以来,Tomcat附带了内存泄漏检测特性,当Webapp的驱动程序中有一个兼容JDBC4.0的驱动程序时,这会导致这种警告消息。/WEB-INF/lib哪辆车-寄存器在webapp启动时使用ServiceLoaderAPI但这不是自动的-注销在webapp关机期间。这个消息纯粹是非正式的,Tomcat已经相应地采取了防止内存泄漏的行动。

你能做什么?

  1. 无视那些警告。托姆凯特做的很好。实际的bug在其他人的代码中(有问题的JDBC驱动程序),而不是在您的代码中。很高兴Tomcat正确地完成了它的工作,并等待JDBC驱动程序供应商修复它,以便您可以升级驱动程序。另一方面,您不应该将JDBC驱动程序放在webapp中/WEB-INF/lib,但仅限于服务器的/lib..如果你还把它放在webapp里/WEB-INF/lib,然后您应该手动注册并使用ServletContextListener.

  2. 降级到Tomcat 6.0.23或更高版本,这样您就不会被这些警告所困扰。但它会悄无声息地漏掉记忆。不知道这到底是不是好消息。这种类型的内存泄漏是背后的主要原因之一。OutOfMemoryError问题在Tomcat热部署期间。

  3. 将JDBC驱动程序移动到Tomcat/lib文件夹,并有一个连接池数据源来管理驱动程序。请注意,Tomcat的内置DBCP在关闭时没有正确地取消注册驱动程序。参见bugDBCP-322作为WONTFIX关闭。您希望将DBCP替换为另一个连接池,它比DBCP做得更好。例如HikariCPBoneCP,或者也许TomcatJDBC池.


查看完整回答
反对 回复 2019-06-18
?
慕少森

TA贡献2019条经验 获得超9个赞

尽管Tomcat为您强制取消JDBC驱动程序的注册,但是在上下文破坏时清理Web应用程序创建的所有资源是很好的做法,以防您迁移到另一个servlet容器,它不像Tomcat那样进行内存泄漏检查。

然而,全面取消司机登记的方法是危险的。返回的一些司机DriverManager.getDrivers()方法可能是由父ClassLoader(即servlet容器的类加载器)加载的,而不是由webapp上下文的ClassLoader加载的(例如,它们可能位于容器的lib文件夹中,而不是Webapp的文件夹中,因此在整个容器中共享)。取消注册将影响其他可能正在使用它们的Web应用程序(甚至容器本身)。

因此,在取消注册之前,应该检查每个驱动程序的ClassLoader是否是Webapp的ClassLoader。因此,在ContextListener的contextD及第()方法中:

public final void contextDestroyed(ServletContextEvent sce) {
    // ... First close any background tasks which may be using the DB ...
    // ... Then close any DB connection pools ...

    // Now deregister JDBC drivers in this context's ClassLoader:
    // Get the webapp's ClassLoader
    ClassLoader cl = Thread.currentThread().getContextClassLoader();
    // Loop through all drivers
    Enumeration<Driver> drivers = DriverManager.getDrivers();
    while (drivers.hasMoreElements()) {
        Driver driver = drivers.nextElement();
        if (driver.getClass().getClassLoader() == cl) {
            // This driver was registered by the webapp's ClassLoader, so deregister it:
            try {
                log.info("Deregistering JDBC driver {}", driver);
                DriverManager.deregisterDriver(driver);
            } catch (SQLException ex) {
                log.error("Error deregistering JDBC driver {}", driver, ex);
            }
        } else {
            // driver was not registered by the webapp's ClassLoader and may be in use elsewhere
            log.trace("Not deregistering JDBC driver {} as it does not belong to this webapp's ClassLoader", driver);
        }
    }}


查看完整回答
反对 回复 2019-06-18
  • 3 回答
  • 0 关注
  • 8309 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信