为什么WebAppClassLoader不会被垃圾回收?

4
我有一个使用spring/hibernate开发的Web服务,每次在Tomcat 7上部署和撤销多次后,我会遇到OutOfMemoryError PermGen Memory泄漏问题。
通过使用Java VisualVM,我注意到以前的webappClassLoader仍然保留在JVM中,因此它们没有被垃圾回收。
这个问题的原因是什么?
如何检测哪些对象仍然引用应用程序类加载器或由其加载的任何对象?
谢谢。

请参见https://dev59.com/DGsz5IYBdhLWcg3wwKqh#7685644。 - Ingo Kegel
1个回答

4
简而言之,您有一个内存泄漏问题。从经验来看,这很可能是由于您的Web应用程序或其使用的库引起的。但也有可能(虽然不太可能)是Tomcat中发现了内存泄漏。
查找内存泄漏的简短版本为:
- 启动Tomcat - 卸载并重新部署有问题的应用程序一次 - 使用分析器检查堆 - 查找WebappClassLoader的实例 - 找到强制保留但属性为started=false的实例 - 跟踪该WebappClassLoader实例的GC根 - 这将指向您的内存泄漏
找到内存泄漏的根本原因可能会更加困难。
有关如何追踪此类内存泄漏以及可能导致它们的更完整的说明,请参见此演示文稿:http://people.apache.org/~markt/presentations/2010-08-05-Memory-Leaks-JavaOne-60mins.pdf

这篇文章的排版链接真的很棒,我会给它加上+1。然后我发现你实际上是它的作者。这是我读过的关于这个主题的最好的材料,我现在想知道为什么这是我第一次阅读它。谢谢 :) - dkateros
谢谢!正如你所说,我得到了已启动=false的WebappClassLoader实例。问题是要跟踪GC根源!我怀疑一个未停止的TimerThread!那么,在Web应用程序卸载后,我该如何停止这个线程呢? - nouro
使用 ServletContextListener,在 contextDestroyed() 事件中停止线程。 - Mark Thomas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接