Sco*_*ott 9 java garbage-collection jvm classloader
我一直在我们的应用程序中处理类加载器泄漏,最终达到了对CL的所有引用都消失的程度.在我的内存分析工具(使用YourKit和jmap/jhat)中,我可以强制GC有时会立即摆脱我的类加载器,但其他时候(取决于应用程序使用情况,但这是我可以得到的具体)当我强制GC,CL实例不会消失.我捕获一个内存快照并查看结果,它说该对象存在,但无法访问.
这是古怪的部分......我只是偶然发现了这一点.
我可以强制使用我想要的全部GC,但实例并没有消失.然而,在10-20分钟之后,如果我再做一次完整的GC,它确实会被收集.
(在此期间,申请大部分是不活动的(并非完全).我的"延长"咖啡休息时间是导致这一发现的事故.)
所以我对这里泄漏的担忧已经消失(希望如此),但问题现在更多是试图解释这种行为.
任何人都知道什么可能导致太阳JVM决定不收集无法访问的类加载器20分钟?
Sun JVM版本详细信息:
java version "1.6.0_23"
Java(TM) SE Runtime Environment (build 1.6.0_23-b05)
Java HotSpot(TM) 64-Bit Server VM (build 19.0-b09, mixed mode)
Run Code Online (Sandbox Code Playgroud)
我认为Jeremy Heiler正处于正确的轨道上,因为它是一个定型问题.基本上,即使GC知道某个对象无法访问,在实际收集对象之前,它可能仍然是无限期的,因为它可能被排队以进行最终确定.终结器线程必须绕过最终化对象(可能需要一段时间,这取决于需要完成多少其他对象以及它们的终结器的外观)然后,在对象完成后,您将需要另一个 GC重新发现该对象在实际收集之前无法访问.
另外,对于Sun JVM上的ClassLoader,它可能直接分配给PermGen.因此,您不需要一个,而是两个完整的PermGen扫描(一个用于将对象放入终结队列,然后是第二个用于实际收集它).由于PermGen扫描很昂贵,我相信Sun JVM根本不会使用默认设置来执行它们,即使使用各种GC调整,它仍然非常不愿意扫描PermGen(特别是如果没有很多其他内存压力) ).
如果不是强迫(嗯,我是说,鼓励)GC使用System.gc()
,如果你做了类似的事情:
System.gc();
System.runFinalization();
System.gc();
Run Code Online (Sandbox Code Playgroud)
当然,即使这不能保证工作,但它至少做了清理大型终结所需对象的最小必要工作.
归档时间: |
|
查看次数: |
1520 次 |
最近记录: |