【发布时间】:2012-06-01 02:52:51
【问题描述】:
当我停止我的项目时,tomcat 说:
以下 Web 应用程序已停止(重新加载、取消部署),但它们之前运行的类仍然存在 加载到内存中,从而导致内存泄漏(使用分析器确认)。
我们在哪里找到哪些类留在内存中?
请帮助我。
【问题讨论】:
标签: jsp tomcat servlets memory-leaks
当我停止我的项目时,tomcat 说:
以下 Web 应用程序已停止(重新加载、取消部署),但它们之前运行的类仍然存在 加载到内存中,从而导致内存泄漏(使用分析器确认)。
我们在哪里找到哪些类留在内存中?
请帮助我。
【问题讨论】:
标签: jsp tomcat servlets memory-leaks
您可以运行jmap -histo,它将显示已加载的类。
例如:
jmap -histo[:live] <pid>
to connect to running process and print histogram of java object heap
if the "live" suboption is specified, only count live objects
Example: jmap -dump:live,format=b,file=heap.bin <pid>
另一种方法是启用类加载调试信息并编写一些脚本来检测剩余加载的内容。
【讨论】:
-verbose:class 选项。
当这种情况发生时,通常内存中有一些东西将 WebappClassLoader(负责为您的 webapp 实例加载类的类加载器)“固定”到内存中。如果您多次重新加载您的 webapp,您将能够看到 WebappClassLoader 实例的数量每执行一次重新加载就会增加 1。这通常不是 Tomcat 中的泄漏,而是直接在您的 web 应用程序代码中的泄漏、您使用的库中的泄漏,或者由一些执行愚蠢操作的特定 Java API 调用触发的泄漏.
首先,请阅读:http://people.apache.org/~markt/presentations/2010-11-04-Memory-Leaks-60mins.pdf。这是对正在发生的事情的极好描述。
其次,使用分析器来确定对 WebappClassLoader 加载的对象的引用。很多时候,只需使用 ServletContextListener 就可以在 webapp 停止时清理这些引用。
第三,如果您发现您使用的库有泄漏,请让他们知道。如果您发现来自 JRE 中的类的泄漏,请查看使用 JreMemoryLeakPreventionListener 的选项:http://tomcat.apache.org/tomcat-6.0-doc/config/listeners.html#JRE_Memory_Leak_Prevention_Listener_-_org.apache.catalina.core.JreMemoryLeakPreventionListener。如果您找到的任何内容都没有选项,请前往 Tomcat 用户并告诉我们缺少的内容:我们会添加它。
【讨论】: