即使没有 gc 根,WebappClassLoader 也会发生内存泄漏

2024-01-01

这是头部转储(更新于 10/29/2013) https://dl.dropboxusercontent.com/u/9210700/java_pid9478.hprof

我正在一个网络应用程序中工作:

  • 雄猫7.0.24
  • Java 6
  • Spring 3(使用 aop - cglib)
  • SLF4J 优于 Log4j
  • 甲骨文一致性

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

Thanks to Yourkit, I was able to check that the WebappClassLoader was Pending Finalization which means that is waiting in the finalizer queue (actually, is not the WebappClassLoader itself but one of his referents). Checking a memory snapshot I found several Finalizer references to Oracle Coherence classes... enter image description here

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

所以,我在想一些finalize执行会破坏某些内容,然后不允许清空终结器队列。但奇怪的是使用 JMX 或jmap -finalizerinfo终结器队列似乎是空的!所有这些都非常令人困惑,所以我继续在其他地方搜索......

你认为这有什么可做的吗?我读过一些关于CGLIB 增强finalize method https://stackoverflow.com/questions/6517348/cglib-methodinterceptor-finalize。如果我有权访问Enhancer我可以按照解释创建回调过滤器here http://neopatel.blogspot.fr/2012/12/cglib-enhancer-and-finalize-method.html但我不知道如何使用 Spring AOP 来管理它。

好吧,在其他地方搜索,我发现了一些弱引用java.lang.reflect.Proxy。这些是jdk动态代理吧?或者它们与内省内存泄漏有关?弱引用?

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

让我们继续吧。

然后,我们还有其他几个弱引用java.io.ObjectStreamClass$Caches。我的许多业务对象都有此类弱引用。

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

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

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

Ah, another thing, I found a weak reference from a tomcat "main" thread that will not be renewed ever by tomcat. I know that my application can leave some thread local var in some tomcat threads, but tomcat 7 renew these threads to avoid class loader memory leaks http://wiki.apache.org/tomcat/MemoryLeakProtection#threadLocalPseudoLeak. enter image description here

我认为这是我的内存快照中最奇怪的事情,但是弱引用是吧?我能用这个做什么?

EDIT:正在阅读java.lang.ref javadoc http://docs.oracle.com/javase/6/docs/api/java/lang/ref/package-summary.html我找到了这个:

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

So, 弱引用实现时可以将对象保留在堆中吗finalize method?

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

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

编辑:管道结果

我尝试过 plumbr,但网络控制台上没有报告。标准输出上仅显示此消息

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                               *
*                                                                            *
******************************************************************************

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

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

即使没有 gc 根,WebappClassLoader 也会发生内存泄漏 的相关文章

随机推荐