重新部署我的应用程序时出现OutOfMemoryError

时间:2014-06-23 10:33:08

标签: java tomcat jetty out-of-memory

我正在开发一个具有插件加载机制的webapp。插件位于单独的jar文件中,并为每个文件加载单独的URLClassLoader s。当我多次重新部署我的应用程序时,有时会得到OutOfMemoryError

我读过这是因为URLClassLoader不能被垃圾收集,因为对它们加载的类的引用仍然存在。

如何在重新部署应用时发布此引用?

该应用程序在开发中的Jetty和生产中的Tomcat上运行。 Tomcat还告诉我这个内存泄漏。

3 个答案:

答案 0 :(得分:0)

插件加载机制的代码位于何处?它是在TOMCAT_HOME / lib或WAR存档中的jar文件中吗?

如果你的所有类都在你的WAR档案中,那么泄漏肯定与tomcats类加载机制的行为有关。

每次(重新)部署应用程序时,Tomcat都会创建一个WebappClassLoader的新实例。在停止或重新部署相应的应用程序后,每个WebappClassLoader实例都有资格进行垃圾回收。在典型的内存泄漏的情况下,WebappClassLoaders不能被垃圾收集,因为对仍然存在的WebappClassLoader的强引用。为了解决此类泄漏,您必须手动删除强引用。

您可以按照以下简单步骤找到泄漏:

  • 启动服务器并部署应用
  • 取消部署您的应用(使用tomcat管理器)
  • 创建堆转储并使用Eclipse MAT
  • 打开它
  • 查找从WebappClassLoader到GC根目录的引用路径(排除弱引用和软引用!)
  • 现在您应该看到阻止WebappClassLoader被垃圾回收的强引用。

有关详细信息,请在此处发布日食MAT的截图。

答案 1 :(得分:-1)

Tomcat 6和threadlocals存在已知问题导致内存泄漏,这应该在Tomcat 7的内存保护功能中修复。

请参阅: http://wiki.apache.org/tomcat/MemoryLeakProtection#customThreadLocal

答案 2 :(得分:-1)

您可以使用ServletContextListener在取消部署Web应用程序时释放引用。

如果您仍然看到PermGen错误,那么您需要修复内存泄漏。根据经验,这很可能是在您的Web应用程序或它正在使用的库中。在Tomcat中发现内存泄漏也是可能的,但不太可能。

用于跟踪内存泄漏的简短版本是:

Start Tomcat
Undeploy and redeploy the problematic application once
Use a profiler to examine the heap
Look for an instances of the WebappClassLoader
Find the one that is strongly held but has an attribute of started = false
Trace the GC roots for that instance of the WebappClassLoader
That will point to your memory leak

找出内存泄漏的根本原因可能会有点困难。

有关如何追踪此类内存泄漏的更详细说明以及可能导致他们看到此演示文稿的内容:http://people.apache.org/~markt/presentations/2010-08-05-Memory-Leaks-JavaOne-60mins.pdf