采用实时堆转储执行System.gc()和死对象回收之间的区别?

时间:2010-11-11 16:08:51

标签: java garbage-collection rmi heap-dump

至少有两种方式,直接或间接地建议JVM花费精力收集垃圾:

  • System.gc()
  • 进行堆转储并仅请求活动对象

在后者中,我可以通过编程方式获取堆转储,例如通过

hotspotMBean = ManagementFactory.newPlatformMXBeanProxy(ManagementFactory.getPlatformMBeanServer(), "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class);
hotspotMBean.dumpHeap(filename, live);

这两项操作在收集非强烈可达对象方面会有什么区别(如果有的话)?

我相信我有证据表明,在存在弱引用,RMI分布式垃圾收集和invisible objects strongly-reachable from the stack的情况下,堆转储方法比System.gc()更具攻击性。特别是那些本地只能很弱地访问并且相对于RMI变为Unreferenced的对象似乎只是由堆转储收集的。我还没有能够将它提炼成一个小的测试用例,但它是可重现的。

(在我被警告不要依赖prod代码中的特定GC行为之前,我不是。我在调查可能的内存泄漏时发现了这一点,并注意到结果因我何时进行堆转储而有所不同。我只是好奇。)

这是在Windows 7上使用HotSpot 64位服务器VM 1.6.0_22。

1 个答案:

答案 0 :(得分:1)

System.gc()可能不那么激进,因为它只是表明它应该运行GC的JVM。然后GC可以自由决定它应该收集(查找和释放所有)死对象,其中一些等等。它可以决定最近发生的伟大收集,而不是再次收集所有对象的时间。 / p>

我认为转储堆并明确只询问生命对象会导致GC精确计算每个对象是否仍然存活。这部分收集工作正在完成,它也不会花费更多的钱来释放死对象使用的内存。

唉,我没有这种行为的有力证据,这是一个疯狂的猜测,而不是一个真实的解释。