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

发布于 2024-10-02 02:04:05 字数 813 浏览 0 评论 0原文

至少有两种方法可以直接或间接地建议 JVM 花费精力来收集垃圾:

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

在后者中,我可以掌握以编程方式进行堆转储,例如通过

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

这两个操作收集非强可达对象有何区别(如果有的话)?

我相信我有证据表明,在存在弱引用、RMI 分布式垃圾收集和 可从堆栈中强访问的不可见对象。特别是那些只能在本地弱访问并且对于 RMI 而言已成为“未引用”的对象似乎仅由堆转储收集。我还无法将其提炼成一个小测试用例,但它是可重现的。

(在我被警告不要依赖产品代码中的特定 GC 行为之前,我不是。我在调查潜在的内存泄漏时发现了这一点,并注意到结果根据我获取堆转储的时间而变化。我只是好奇。)

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

There are at least two ways, directly or indirectly, of suggesting that the JVM expend effort collecting garbage:

  • System.gc()
  • taking a heap dump and requesting live objects only

In the latter, I can get hold a heap dump programmatically, for example through

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

What difference, if any, is there between what these two operations will do to collect non-strongly-reachable objects?

I believe I have evidence that the heap dump approach is more aggressive than System.gc() in the presence of some combination of weak references, RMI distributed garbage collection and invisible objects strongly-reachable from the stack. In particular that objects that are only weakly reachable locally and have become Unreferenced with respect to RMI appear to be collected only by the heap dump. I haven't yet been able to distil this into a small test case, but it is reproducible.

(Before I'm warned against relying on particular GC behaviour in prod code, I'm not. I discovered this while investigating a potential memory leak, and noticed that the result varied depending on when I took the heap dump. I'm just curious.)

This is using HotSpot 64-Bit Server VM 1.6.0_22 on Windows 7.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

笨死的猪 2024-10-09 02:04:05

System.gc() 可能不那么激进,因为它只是指示 JVM 它应该运行 GC。然后,GC 可以自由地决定它应该收集(查找并释放内存)所有死对象(其中一些对象等)。它可以决定之前的伟大收集发生得太晚了,现在不是再次收集所有对象的时候。

我相信转储堆并仅显式询问存活对象将导致 GC 精确计算每个对象是否仍存活。这部分收集工作已经完成,释放死对象所使用的内存也不会花费太多。

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

The System.gc() is probably less aggressive because it just indicates the JVM that it should run the GC. The GC is then free to decide it should collect (find and free memory of) all dead objects, some of them, etc. It can decide the previous great collection happened too recently and it is not the time to collect all objects again.

I believe that dumping heap and explicitly asking only the living objects will cause the GC to compute precisely for each object if it should still be alive. This part of the collecting work being done, it does not cost much more to free the memory used by dead objects as well.

Alas I have no strong evidence of this behaviour and this is more a wild guess than a real explanation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文