java 网络应用程序中的内存泄漏

Memory leak in java web application

我有一个使用 hibernate 3.6.4 和 spring 3.2.4(mvc、tx 和安全性)的 Web 应用程序并且是 运行 in tomcat 7。每次我在没有重新启动 tomcat 的情况下部署了我的应用程序的更新版本,然后 tomcat 使用的内存增加了大约 50MB。

我创建了一些堆转储并使用 Eclipse 内存分析器对其进行了分析。我发现每次重新部署应用程序时,都会创建一个新的 WebappClassLoader 实例。但即使在我使用 tomcat 管理器停止应用程序之后,WebappClassLoader 仍保留在内存中并且不会被垃圾收集。 所以在每次重新部署后,一个额外的 WebappClassLoader 保留在内存中并使用大约 50MB 的内存。

我使用 Eclipse 内存分析器来查找从 WebappClassLoader 到 GC 根的引用路径。结果我找不到任何可以阻止 WebappClassLoaders 被垃圾收集的强引用。

那么,是什么让 WebappClassLoaders 保持活力?我还能在哪里调查以找出是什么阻止了 WebappClassLoader 的垃圾收集?

我认为可能存在阻止 GC 完成垃圾收集的阻塞 finalize() 方法。但是我该如何检查呢?

Class 加载程序理论上在没有引用对象实例时被垃圾收集,并且 class 卸载不是必需的,但实际上它似乎更成问题。

我会推荐阅读这两篇文章

http://frankkieviet.blogspot.com.au/2006/10/classloader-leaks-dreaded-permgen-space.html

http://frankkieviet.blogspot.com.au/2006/10/how-to-fix-dreaded-permgen-space.html

我不是 Tomcat 的专家,它是重新部署的实现,但在我们使用 JBoss 的日子里,我们遇到了非常相似的情况。这是因为 PermGen space 不是垃圾收集器,每个新部署都会将 类 放在那里。 所以如果你不在 Java 8 上,请检查实际的 "leak" 是否不在 permgen space 中。

您可以按照Anatomy of a PermGen Memory Leak tutorial too. They are using Java Visual VM but the steps and the things to check should be the same in Eclipse Memory Analizer too. In this演示文稿中介绍的步骤进行操作,您可以找到此类泄漏的可能原因。

另请注意,如果您没有看到任何对 WebappClassLoaders 的引用,则可能是 JVM 有大量 PermGen 并且正在推迟驱逐。您可以通过 运行 较小的 PermGen 大小轻松检查并进行几次重新部署。