javaweb应用程序中的内存泄漏
我有一个web应用程序,它使用hibernate 3.6.4和spring 3.2.4(mvc、tx和security),并且运行在tomcat 7中。每次我在不重新启动tomcat的情况下部署新版本的应用程序时,tomcat使用的内存都会增加大约50MB
我创建了一些堆转储,并使用Eclipse内存分析器对它们进行了分析。我发现每次重新部署应用程序时,都会创建一个新的WebappClassLoader实例。但是,即使在我使用tomcat manager停止应用程序之后,WebappClassLoader仍保留在内存中,不会被垃圾收集。 因此,在每次重新部署之后,一个额外的WebappClassLoader将保留在内存中,并使用大约50MB的内存
我使用Eclipse内存分析器来查找从WebappClassLoader到GC根的引用路径。结果,我找不到任何可以防止WebAppClassLoader被垃圾收集的强引用
那么,是什么让webappclassloader保持活力呢?我还可以在哪里进行调查以找出阻止WebappClassLoader进行垃圾收集的原因
我认为可能存在阻止GC完成垃圾收集的blocking finalize()方法。但是我怎么能检查这个
# 1 楼答案
我不是Tomcat及其重新部署实现方面的专家,但在我们使用JBoss的时候,我们也遇到过类似的情况。这是因为PermGen空间不是垃圾收集的,每个新部署都会将类放在其中。 因此,如果您不在Java8上,请检查实际的“泄漏”是否不在permgen空间中
# 2 楼答案
理论上,类装入器是在没有对象实例引用且不需要卸载类的情况下进行垃圾收集的,但在实践中,问题似乎更大
我建议读这两篇文章
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
# 3 楼答案
您也可以按照Anatomy of a PermGen Memory Leak教程中介绍的步骤进行操作。他们正在使用Java Visual VM,但是在Eclipse内存分析器中检查的步骤和内容也应该相同。在this演示中,您可以找到此类泄漏的可能原因
还请注意,如果您没有看到任何对
WebappClassLoaders
的引用,则可能是JVM
有大量的PermGen
并且正在推迟驱逐。您可以通过使用较小的PermGen
大小运行并进行几次重新部署来轻松检查这一点