【问题标题】:WebappClassLoader memory leak even with no gc rootsWebappClassLoader 内存泄漏,即使没有 gc 根
【发布时间】:2013-10-19 19:45:18
【问题描述】:

HERE IS THE HEAD DUMP (UPDATED ON 10/29/2013)

我正在使用以下 Web 应用程序:

  • Tomcat 7.0.24
  • Java 6
  • Spring 3(使用 aop - cglib)
  • SLF4J 优于 Log4j
  • Oracle 一致性

经过大量工作,我设法删除了对类加载器的所有强引用,现在它是垃圾收集器的候选对象。那么,内存泄漏解决了吗?当然不是!因为在多次热部署后,由于 PermGen 空间而出现 OOME。

感谢 Yourkit,我能够检查到 WebappClassLoader 是 Pending Finalization 这意味着它正在终结器队列中等待(实际上,不是 WebappClassLoader 本身,而是他的一个参照物)。检查内存快照,我发现了几个Finalizer 对 Oracle Coherence 类的引用...

这看起来“不错”:由于移除所有强引用(杀死所有一致性线程、移除 java 安全提供程序等)所做的所有艰苦工作,Coherence 对象正在等待被垃圾收集。我觉得这里没什么可做的。

所以,我在考虑一些 finalize 执行会破坏某些东西,然后不允许清空终结器队列。但奇怪的是,使用 JMX 或jmap -finalizerinfo 终结器队列似乎是空的!这一切都非常令人困惑,所以我一直在其他地方寻找......

你认为这可以在这里做吗?我读过一些关于CGLIB enhancing the finalize method 的文章。如果我可以访问Enhancer,我可以按照here 的说明创建一个回调过滤器,但我不知道如何使用 Spring AOP 来管理它。

嗯,在其他地方搜索,我发现了几个来自java.lang.reflect.Proxy 的弱引用。这些是jdk动态代理对吗?或者它们与自省内存泄漏有关?有弱引用?

INFO:我正在使用 Spring 的上下文侦听器来刷新 instrospector 的缓存 (java.beans.Introspector.flushCaches())。 我还能用这个做什么?

让我们继续。

然后,我们还有来自java.io.ObjectStreamClass$Caches 的其他几个弱引用。我的很多业务对象都有这种弱引用。

也许我需要刷新这些缓存。 但是如何?

然后我们有这些与com.sun.internal.ResourceManager、java.util.logging.Logging 和java.lang.reflect.Proxy 相关的弱引用

我能用这个弱引用做什么?我需要担心这个还是问题出在终结队列上?任何线索都会有所帮助......真的:-D

啊,另一件事,我从一个tomcat“主”线程中发现了一个弱引用,它永远不会被tomcat更新。我知道我的应用程序可以在一些 tomcat 线程中留下一些线程本地变量,但是tomcat 7 renew these threads to avoid class loader memory leaks。

我认为这是我的记忆快照中最奇怪的事情,但是弱引用对吗?我能用这个做什么?

编辑:阅读java.lang.ref javadoc我发现了这个:

一个对象是弱可达的,如果它既不是强可达也不是软可达,但可以通过遍历弱引用到达。当对弱可达对象的弱引用被清除时,该对象就有资格进行终结。

那么,弱引用可以在实现finalize方法时将对象保留在堆中吗?

同时我找到了答案,我设法删除了对我的类加载器的所有弱引用,但有两个:ClassLoaderLogManager.classLoaderLoggers 和与 tomcat 线程相关的一个。

注意:实际上,我设法删除了第一个,但是这个引用是由 tomcat 在取消部署之后/期间再次设置的。

编辑:PLUMBR 结果

我已经尝试过 plumbr,但在 Web 控制台上没有报告。标准输出上只有这条消息

Dumping heap to /opt/tomcat7/headdumps/java_pid9478.hprof ...
Heap dump file created [348373628 bytes in 3.984 secs]
#
# An unexpected error has been detected by Java Runtime Environment:
#
#  Internal Error (javaCalls.cpp:40), pid=9478, tid=1117813056
#  Error: guarantee(!thread->is_Compiler_thread(),"cannot make java calls from the compiler")
#
# Java VM: Java HotSpot(TM) 64-Bit Server VM (11.2-b01 mixed mode linux-amd64) [thread 1110444352 also had an error]
# An error report file with more information is saved as:
# [thread 1110444352 also had an error]
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp
#
******************************************************************************
*                                                                            *
* Plumbr has noticed that JVM has thrown an OutOfMemoryError: PermGen space. *
*                                                                            *
* You can increase PermGen size with -XX:MaxPermSize parameter.              *
* If you encountered this error after a redeploy, please read next article:  *
* http://plumbr.eu/blog/what-is-a-permgen-leak                               *
*                                                                            *
******************************************************************************

【问题讨论】:

  • 在 OOM 发生后是否有堆转储可供下载?也许我们可以调查一下。
  • 嘿@Nikem!那将是非常好的!我也尝试过使用 plumbr 没有任何成功:-( 这是转储:dl.dropboxusercontent.com/u/9210700/java_pid12165.hprof
  • 您是否尝试在连接 Plumbr 时重新部署您的应用程序?如果您愿意,您可以通过 support@plumbr.eu 与我们联系,以调查 Plumbr 对此案例存在问题的原因。
  • 我已经安装了plumbr并且我设法使用它,但没有检测到内存泄漏!我会再尝试。我会及时通知你的!
  • 我推荐以下步骤:启动你的应用程序并连接 Plumbr,运行一段时间,重新部署应用程序,让 Plumbr 思考大约 5 分钟。如果没有帮助,请联系我们:)

标签: java tomcat memory-leaks classloader yourkit


【解决方案1】:

我认为 Yourkit 把你引向了错误的道路。

我已经使用 Eclipse 内存分析器查看了您的堆转储。它表明,类 com.inovasoftware.iap.data.access.platform.datarepository.CoherenceDataRepository$$EnhancerByCGLIB$$180c0a4e 引用了 WebappClassLoader,该实例在某个线程局部变量中是活动的。一些谷歌搜索显示了这一点: https://hibernate.atlassian.net/browse/HHH-2481

所以升级 Hibernate 版本可能会有所帮助。

【讨论】:

  • 感谢您提供此信息!我现在就杀掉那个引用!我会及时通知你的!
  • 嘿@Nikem!感谢您的发现!我设法在本地释放线程,但类加载器仍然“等待完成”(在 yourkit 上)。我还检查了 EMA,我只看到了对一些 Coherence 对象的终结器引用。如果可以,请查看新的 head dump dl.dropboxusercontent.com/u/9210700/Tomcat-2013-10-25.hprof
  • 我会调查的。你还OOM吗?
  • 是的......经过 3/4 次热部署。在此先感谢 :-)
  • 这很奇怪。我看不到任何重复的类加载器。您的应用程序只有一个 WebappClassLoader。这个转储是从几次重新部署中提取的吗?对我来说它看起来很新鲜。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-09
  • 2011-12-10
  • 2013-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多