java - 有没有办法避免Tomcat中的卸载内存泄漏?

标签 java spring tomcat memory-leaks jaxb

此问题适用于曾经在 Tomcat 管理器中测试过“查找泄漏”按钮并得到如下结果的任何人:

The following web applications were stopped (reloaded, undeployed), but their classes from previous runs are still loaded in memory, thus causing a memory leak (use a profiler to confirm):
/leaky-app-name

我假设这与频繁重新部署时经常遇到的“Perm Gen space”错误有关。

所以我在部署时在 jconsole 中看到的是我加载的类从大约 2k 变为 5k。然后您会认为取消部署应该将它们降回 2k,但它们仍保持在 5k。

我也尝试过使用以下 JVM 选项:

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

我确实看到 Perm Gen 空间使用量有非常小的下降,但不是我预期的,加载的类数也没有下降。

那么有没有办法配置 Tomcat 或设计您的应用程序以在取消部署时更好地卸载?或者在一些主要的调试 session 之后我们是否坚持重新启动服务器?

Tomcat 版本输出:

Server version: Apache Tomcat/6.0.29
Server built: July 19 2010 1458
Server number: 6.0.0.29
OS Name: Windows 7
OS Version: 6.1
Architecture: x86
JVM Version: 1.6.0_18-b07
JVM Vendor: Sun Microsystems Inc.

更新:

感谢 celias 的回答,我决定做更多的挖掘工作,我想我确定罪魁祸首是在我的应用程序中,这要归功于 CXF、Spring 和 JAXB。

在我学会了如何分析 Java 应用程序后,我将分析器指向 Tomcat,并拍摄了一些堆转储和快照,以查看对象和类在内存中的样子。我发现在我的 CXF/JAXB (wsdl2java) 生成的类中使用的 XML 模式中的一些枚举在取消部署后仍然存在。根据我的堆转储,看起来对象绑定(bind)到了 map 。免责声明:我承认我对分析和跟踪对象的调用树在 Java 中可能具有挑战性。

另外我应该提到我什至没有调用服务,只是部署然后取消部署它。对象本身似乎是通过部署时从 Spring 启动的反射加载的。我相信我遵循了在 Spring 中设置 CXF 服务的约定。所以我不能 100% 确定这是 Spring/CXF、JAXB 还是反射的错误。

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

最佳答案

如果您想确保不会导致泄漏,您必须执行以下操作:

  • 确保您的 Web 应用程序不使用 Web 容器共享库中的任何 Java 类。如果您有任何共享库,请确保这些库中的对象没有强引用
  • 避免使用静态变量,尤其是在 HashTable、Sets 等 java 对象上。如果需要,请确保调用 remove 以释放带有映射、列表的对象...

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

关于java - 有没有办法避免Tomcat中的卸载内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4565105/

相关文章:

java - JTree:如何检查当前节点是否为文件

java - 反序列化空字符串时防止Gson返回null

java - 运行 spring 服务器时 JRebel-JVMTI 错误

java - Tomcat 类加载器 : priority between WebappX & Common

eclipse - 使用 Eclipse 导出一个独特的 war holding RESTlet 和 Servlet 一起为 Tomcat 工作

java - 在 Spring MVC 中不使用 @Valid 验证 POJO

java - MySQL - "SHOW VARIABLES LIKE ' %version %'"在我的 Java 应用程序中不工作

spring - 为什么 @WebMvcTest 中的 POST 请求使用 permitAll() 返回 403

java - 当前没有 session 绑定(bind)到执行上下文

tomcat - 在 Eclipse 中,如何让正在运行的 tomcat 从依赖的 maven 项目中看到我的源代码更改?