问题描述
我正在使用以下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.ResourceManager
,java.util.logging.Logging
和java.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:
那么,弱引用在实现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根的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!