WebappClassLoader内存泄漏,即使没有gc根 [英] WebappClassLoader memory leak even with no gc roots

查看:221
本文介绍了WebappClassLoader内存泄漏,即使没有gc根的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里是头上的转储(2013年10月29日更新)

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

I'm working in a webapp with:

  • Tomcat 7.0.24
  • Java 6
  • Spring 3(带有aop-cglib)
  • 通过Log4j的SLF4J
  • Oracle一致性

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

After a lot of work, I managed to remove all the strong reference to the class loader and now it is a candidate for the garbage collector. So, memory leak solved? Of course not! Because after several hot deployments a OOME appears due to PermGen space.

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

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

这似乎是"okey":由于去除所有强引用(杀死所有一致性线程,删除Java安全提供程序等)所做的所有艰苦工作,一致性对象正等待被垃圾回收.我认为这里无事可做.

This seems "okey": Coherence objects are waiting to be garbage collected thanks to all the hard work done removing all the strong references (killing all coherence threads, removing java security providers, etc). I think that there is nothing to do here.

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

So, I was thinking about some finalize execution that breaks something and then not allowing empty the finalizer queue. But the weird thing is that using JMX or jmap -finalizerinfo the finalizer queue seems to be empty! All this is very confusing so I kept searching in other places...

您认为这是要做的事吗?我已经阅读了有关的内容CGLIB增强了finalize方法.如果我可以访问Enhancer,则可以按照在这里,但我不知道如何使用Spring AOP进行管理.

Do you think that is something to do here? I've read something about CGLIB enhancing the finalize method. If I have access to Enhancer I can create a callback filter as explained here but I dunno how to manage this with Spring AOP.

好吧,在其他地方搜索时,我发现了java.lang.reflect.Proxy的一些弱引用.这些是jdk动态代理吗?还是与自省内存泄漏有关?参考力不强?

Well, searching in other places, I found several weak references from java.lang.reflect.Proxy. These are jdk dynamic proxies right? or they are related to Introspection memory leaks? with weak references?

信息:我使用的是Spring的上下文侦听器,该侦听器会刷新内省检查器的缓存(java.beans.Introspector.flushCaches()). 我还能做什么?

INFO: I'm using a Spring's context listener that flushes instrospector's caches (java.beans.Introspector.flushCaches()). What else I can do with this?

让我们继续.

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

Then, we have several other weak references from java.io.ObjectStreamClass$Caches. A lot of my business objects have these kind of weak references.

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

Maybe I need flushing these caches. But how??

然后我们有与com.sun.internal.ResourceManagerjava.util.logging.Loggingjava.lang.reflect.Proxy

如何处理这些弱引用?我是否需要担心这个问题,还是问题在终结器队列上?任何线索都将有所帮助...真的:-D

What I can do with this weak references? Do I need to worry about this or the problem is on the finalizer queue? Any clue will be of help ... really :-D

啊,另一件事,我从tomcat的主"线程中发现了一个弱引用,它永远不会被tomcat更新.我知道我的应用程序可以在某些tomcat线程中保留一些线程本地变量,但是 tomcat 7更新了这些线程以避免类加载器内存泄漏.

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.

我认为这是我的内存快照中最奇怪的事情,但是裁判弱吗?我该怎么办?

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

Reading the java.lang.ref javadoc i found this:

如果对象既不是强可达也不是软可达,但是可以通过遍历弱引用来实现,则它是弱可达的.清除对弱可访问对象的弱引用后,该对象将有资格进行终结处理.

An object is weakly reachable if it is neither strongly nor softly reachable but can be reached by traversing a weak reference. When the weak references to a weakly-reachable object are cleared, the object becomes eligible for finalization.

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

So, can weak references retain objects in the heap when they implement a finalize method?

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

Meanwhile i found an answer to this, I manage to remove all the weak references to my classloader but two: ClassLoaderLogManager.classLoaderLoggers and the one related to the tomcat thread.

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

NOTE: Actually, I managed to remove the first one but this reference is set again by tomcat after/during undeployment.

完整结果

我已经尝试过浏览器浏览器,但是在Web控制台上没有任何报告.标准输出上只有此消息

I've tried plumbr and no reports on the web console. Only this message on the standard output

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已将您引向错误的路径.

I think Yourkit has led you to the wrong path.

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

I have looked into your heap dump using Eclipse Memory Analyzer. It showed, that WebappClassLoader is referenced by class com.inovasoftware.iap.data.access.platform.datarepository.CoherenceDataRepository$$EnhancerByCGLIB$$180c0a4e, which instance is alive in some thread local variable. Some googling showed this: https://hibernate.atlassian.net/browse/HHH-2481

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

So may be upgrading Hibernate version will be of help.

这篇关于WebappClassLoader内存泄漏,即使没有gc根的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆