我正在使用以下 Web 应用程序:
- 雄猫 7.0.24
- 爪哇 6
- Spring 3(使用 aop - cglib)
- SLF4J 优于 Log4j
- 甲骨文一致性
经过大量工作,我设法删除了对类加载器的所有强引用,现在它是垃圾收集器的候选对象。那么,内存泄漏解决了吗?当然不是!因为在几次热部署之后,由于 PermGen 空间而出现了 OOME。
多亏了 Yourkit,我能够检查到WebappClassLoader
是Pending Finalization,这意味着它正在终结器队列中等待(实际上,不是它WebappClassLoader
本身,而是他的一个参照物)。检查内存快照,我发现了几个Finalizer
对 Oracle Coherence 类的引用......
这似乎是“好的”:由于删除所有强引用(杀死所有一致性线程、删除 java 安全提供程序等)所做的所有艰苦工作,Coherence 对象正在等待被垃圾收集。我认为这里没有什么可做的。
所以,我在考虑一些finalize
破坏某些东西的执行,然后不允许清空终结器队列。但奇怪的是,使用 JMX 或jmap -finalizerinfo
终结器队列似乎是空的!这一切都非常令人困惑,所以我一直在其他地方寻找......
你认为这是要做的事情吗?我读过一些关于CGLIB 增强finalize
方法的内容。如果我有权访问,我可以按照此处Enhancer
的说明创建一个回调过滤器,但我不知道如何使用 Spring AOP 来管理它。
好吧,在其他地方搜索,我从java.lang.reflect.Proxy
. 这些是jdk动态代理对吗?或者它们与自省内存泄漏有关?有弱参考?
信息:我正在使用 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 更新这些线程以避免类加载器内存泄漏。
我认为这是我的记忆快照中最奇怪的事情,但是一个弱参考对吗?我能用这个做什么?
编辑:阅读java.lang.ref
javadoc我发现了这个:
一个对象是弱可达的,如果它既不是强可达也不是软可达,但可以通过遍历弱引用来达到。当对弱可达对象的弱引用被清除时,该对象就有资格进行终结。
那么,弱引用在实现方法的时候,是否可以将对象保留在堆中呢?finalize
同时我找到了一个答案,我设法删除了对我的类加载器的所有弱引用,但有两个:ClassLoaderLogManager.classLoaderLoggers
一个与 tomcat 线程相关。
注意:实际上,我设法删除了第一个,但是在取消部署之后/期间,tomcat 再次设置了此引用。
编辑:铅锤结果
我已经尝试过 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 *
* *
******************************************************************************