有没有办法来避免Tomcat的解除部署内存泄漏?

这个问题对于任何曾经testing过Tomcatpipe理器中的“Find leaks”button的人来说都是这样的:

以下Web应用程序已停止(重新加载,取消部署),但其以前运行的类仍然加载到内存中,从而导致内存泄漏(使用分析器进行确认):
/漏的应用程序名称

我认为这与您经常重新部署时经常遇到的“Perm Gen空间”错误有关。

所以当我部署的时候我在jconsole中看到的是我的加载类从大约2k到5k。 那么你会认为一个部署会让他们回到2K,但他们仍然在5K。

我也试过使用下面的JVM选项:

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

我看到使用Perm Gen空间的次数非常less,但不是我所期望的,而且加载的类数没有下降。

那么有没有一种方法来configurationTomcat或devise你的应用程序卸载更好地卸载? 还是我们坚持重新启动服务器后,一些主要的debugging会议?

Tomcat版本输出:

服务器版本:Apache Tomcat / 6.0.29
build立的服务器: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。

在学习了如何configurationJava应用程序之后,我将分析器指向了Tomcat,并采取了一些堆转储和快照来查看内存中对象和类的内容。 我发现在我的CXF / JAXB(wsdl2java)生成的类中使用的XML模式中的一些枚举在部署之后仍然存在。 根据我的堆转储它看起来像对象被绑定到一个地图。 免责声明:我承认我仍然有点绿色与分析和追踪对象的调用树可以在Java中具有挑战性。

另外我应该提到,我甚至没有调用服务,只是部署,然后取消部署。 这些对象本身似乎是通过部署时从Spring发起的reflection来加载的。 我相信我遵循了在春季build立CXF服务的惯例。 所以我不是100%确定这是Spring / CXF,JAXB还是reflection的错误。

作为一个方面的说明:有问题的应用程序是使用Spring / CXF的Web服务,而XML恰好是一个相当复杂的模式( NIEM的扩展)。

如果你想确保不造成泄漏,你必须做到以下几点:

  • 确保您的Web应用程序不使用Web容器共享库中的任何Java类。 如果您有任何共享库,请确保没有强引用这些库中的对象
  • 避免使用静态variables,特别是像HashTable,集合等Java对象。如果您需要,请确保您调用删除释放与地图,列表的对象…

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

Tomcat 7应该带来这方面的改进。 请参阅Apache Tomcat 7的特性 ,标题为“ 不要泄漏!

他们认为现在可以处理由Web应用程序引起的大量内存泄漏。 不幸的是,它仍处于testing阶段。

除此之外,我可以说我已经有了相同的经历,还没有find解决办法。 事后部署通常需要重新启动Tomcat。 我不知道谁是罪魁祸首:我的Web应用程序,Tomcat的,hibernate,挂毯或其中几个。