怀疑 Jdbc 和 Tomcat 的内存泄漏

Posted

技术标签:

【中文标题】怀疑 Jdbc 和 Tomcat 的内存泄漏【英文标题】:Suspected memory leak with Jdbc and Tomcat 【发布时间】:2015-03-31 23:59:45 【问题描述】:

我的 tomcat 日志中有这些消息:

" org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc Web 应用程序注册了 JBDC 驱动程序 [com.mysql.jdbc.Driver],但在 Web 应用程序停止时未能取消注册。为防止内存泄漏,已强制注销 JDBC 驱动程序。”

"org.apache.catalina.loader.WebappClassLoader clearReferencesThreads 严重:Web 应用程序似乎启动了一个名为 [pool-820-thread-1] 的线程,但未能停止它。这很可能会造成内存泄漏。”

实际上,我的 java 项目中有一个 JDBC 驱动程序 (.jar),我总是将它作为 .war 部署在 tomcat 服务器上(意味着驱动程序总是在 war/libs 目录中)。

经过搜索,我找到了一个很好的答案 here,但不幸的是,我还不能对 *** 发表评论,以了解有关已接受答案的更多详细信息。

这是我的问题: - 答案是否建议从 war/libs 目录中完全删除 .jar ? - 如果是,我应该把它放在哪里?因为我不知道如何完全摆脱 .jar 并且仍然能够在本地对数据库进行测试。

请对此提出建议。

【问题讨论】:

【参考方案1】:

从 Tomcat 6.0 开始,就有了检测类加载器内存泄漏的功能。阅读更多here。 tomcat 的上述消息纯粹是为了提供信息,并且 tomcat 已经采取了足够的措施,通过取消注册Driver 来避免类加载器泄漏。

为了防止它,正如您正确指出的那样,您可以将 jar 完全移动到 tomcat 的 lib 文件夹,它不会受到应用程序上下文重新加载的影响。或者您可以显式调用DriverManager.deregister(driver)。 (阅读here)

了解有关 ClassLoader 泄漏的更多信息 (here)

要了解为什么建议将其从应用程序WEB_INF/lib 移至tomcat lib,您可以阅读更多here.

根据评论中的查询进行编辑

不建议使用多个 jar,因为它可能导致 classcastexception。每个类由类名和类加载器的组合标识。看this,通过一个例子更清楚地理解。

根据我的说法,更好的方法是编写一个 servlet 上下文侦听器,并在上下文销毁时显式取消注册您的驱动程序。这样您就可以将 jdbc 驱动程序保留在您的 web-inf/lib 中,而无需将其移动到 tomcat/lib

即使您将 jar 保存在多个位置,根据 tomcat 遵循的与 java 委托模型不同的类加载器层次结构(更多信息here),tomcat 也会首先在您的web-inf/lib 中提取 jar。

【讨论】:

感谢您的回答Summet!尽管如此,如果我将驱动程序 .jar 移动到服务器 tomcat lib 目录中,我剩下的问题是知道如何处理本地开发(因为在本地,我没有 tomcat 用于调试目的......)。或者我应该在本地使用 .jar,然后在每次部署到服务器之前将其从我的 .war 中删除?问候, 那么,如果我理解的很好,我可以复制一份吗?

以上是关于怀疑 Jdbc 和 Tomcat 的内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

tomcat7 - jdbc 数据源 - 这很可能会造成内存泄漏

Tomcat如何检测内存泄漏

JDBC 大容量复制中可能存在内存泄漏

独立的 jdbc-pool 实现内存泄漏

内存泄漏和内存溢出的区别

javascript中的关闭和回调内存泄漏