有没有办法避免Tomcat中的undeployment memory leaks?

30 浏览
0 Comments

有没有办法避免Tomcat中的undeployment memory leaks?

这个问题是针对那些曾经测试过 Tomcat 管理器中的“查找泄漏”按钮并得到以下结果的任何人的:

以下 Web 应用程序已停止(重新加载、卸载),但其上一次运行的类仍加载在内存中,因此导致内存泄漏(请使用分析器确认):

/泄漏的应用程序名称

我认为这与经常重新部署时经常出现的“Perm Gen space”错误有关。

所以当我部署时,在 jconsole 中看到我的加载类从大约 2k 增加到 5k。然后你可能认为卸载应该将它们降回到 2k,但它们仍然保持在 5k。

我还尝试使用以下 JVM 选项:

-XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC -XX:+CMSPermGenSweepingEnabled

我确实看到了 Perm Gen 空间使用量的非常小的下降,但不是我所期望的,并且加载的类计数没有下降。

那么,有没有一种方法可以配置 Tomcat 或设计您的应用程序,在卸载时更好地卸载?或者我们在一些主要的调试会话之后被迫重新启动服务器?

Tomcat 版本输出:

服务器版本:Apache Tomcat/6.0.29

服务器构建时间:2010 年 7 月 19 日 1458

服务器编号:6.0.0.29

操作系统名称:Windows 7

操作系统版本:6.1

架构:x86

JVM 版本:1.6.0_18-b07

JVM 供应商:Sun Microsystems Inc.

更新:

由于 celias 的回答,我决定再深入挖掘一下,我认为我确定了罪魁祸首是由于 CXF、Spring 和 JAXB 在我的应用程序中引起的。

在学习如何对Java应用程序进行分析后,我将分析器指向了Tomcat,并进行了一些堆转储和快照,以查看内存中的对象和类的情况。我发现,我的 CXF/JAXB(wsdl2java) 生成的类中使用的一些XML模式中的枚举在卸载后仍然存在。根据我的堆转储,这些对象似乎与一个 Map 相关联。免责声明:我承认我在分析和追踪对象的调用树方面仍有些经验不足,这在 Java 中可能会很具有挑战性。

此外,我应该提到,我甚至没有调用该服务,只是部署了它然后卸载了它。这些对象本身似乎是通过 Spring 在部署时启动的反射加载的。我相信我遵循了在 Spring 中设置 CXF 服务的惯例。所以我并不百分之百确定这是 Spring/CXF、JAXB 还是反射的问题。

顺带一提:所讨论的应用程序是使用 Spring/CXF 的 Web 服务,并且 XML 恰好是一个相当复杂的模式(NIEM 的扩展)。

admin 更改状态以发布 2023年5月24日
0
0 Comments

Tomcat 7据说在这方面有所改进。请参阅Apache Tomcat 7的功能,标题为“没有泄漏!”。

他们认为他们现在可以处理由Web应用程序引起的许多内存泄漏。不幸的是,它仍处于测试版。

除此之外,我只能说我有同样的经历,还没有找到解决方案。通常部署需要之后重启Tomcat。我不知道罪魁祸首是谁:我的Web应用程序、Tomcat、Hibernate、Tapestry或几个的问题。

0
0 Comments

如果你想确保不会引起泄漏,你需要执行以下步骤:

  • 确保你的 Web 应用程序不使用任何在 Web 容器共享库中的 Java 类。如果你有任何共享库,请确保在这些库中没有对对象的强引用
  • 避免使用静态变量,特别是对于像 HashTable、Sets 等 Java 对象。如果必须使用,确保使用 map、list 等 remove 方法释放对象。

这里还有一篇关于 ThreadLocal 和内存泄漏的好文章- http://blog.arendsen.net/index.php/2005/02/22/threadlocals-and-memory-leaks-revisited/

0