即使没有gc root,WebappClassLoader内存也会泄漏

时间:2013-10-19 19:45:18

标签: java tomcat memory-leaks classloader yourkit

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

我正在使用以下网址工作:

  • Tomcat 7.0.24
  • Java 6
  • Spring 3(使用aop-cglib)
  • SLF4J over Log4j
  • Oracle Coherence

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

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

这似乎是“okey”:Coherence对象正在等待垃圾收集,这要归功于删除所有强引用(删除所有一致性线程,删除java安全提供程序等)所做的所有艰苦工作。我认为这里没什么可做的。

所以,我正在考虑一些finalize执行会破坏某些内容然后不允许清空终结器队列。但奇怪的是,使用JMX或jmap -finalizerinfo终结器队列似乎是空的!这一切都很混乱所以我一直在其他地方搜索......

你觉得这可以做点什么吗?我读过有关CGLIB enhancing the finalize method的内容。如果我有权访问Enhancer,我可以按照here的说明创建一个回调过滤器,但我不知道如何使用Spring AOP来管理它。

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

enter image description here

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

让我们继续。

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

enter image description here enter image description here

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

然后我们将这些弱引用与com.sun.internal.ResourceManagerjava.util.logging.Loggingjava.lang.reflect.Proxy

相关联

enter image description here

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

啊,另一件事,我发现一个tomcat“main”线程的弱引用,不会被tomcat更新。我知道我的应用程序可以在某些tomcat线程中留下一些线程局部变量,但是tomcat 7 renew these threads to avoid class loader memory leaksenter image description here

我认为这是我的记忆快照中最奇怪的事情,但这是一个弱的参考权吗?我能做些什么呢?

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

  

如果某个对象既不强也不可轻松到达,则可以通过遍历弱引用来访问该对象。当清除对弱可达对象的弱引用时,该对象将有资格进行最终确定。

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

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

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

编辑:PLUMBR结果

我在网络控制台上尝试了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                               *
*                                                                            *
******************************************************************************

1 个答案:

答案 0 :(得分:2)

我认为Yourkit已经导致你走错了路。

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

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

MAT screenshot