Java GC:Java GC如何清除WeakReference对象?

Java GC: How does Java GC clears WeakReference object?

首先我想让你知道这是一个比实际问题更理论化的问题,我只是好奇弱引用对象是如何被释放的。
让我们快速记住Java中的弱引用是什么。粗略地说 WeakReference 意味着当没有指向“我”的强引用时,您可以随时取消分配“我”,直到“我”仍然存在。此外,我们知道有许多不同的垃圾收集器使用不同的收集技术。比如以前的Android是基于Dalvik GC的,就是stop-the-world,字面意思就是应用在内存清理的时候被挂起。后来 Dalvik 被 ART 取代——由 Google 编写的新版本的 GC,由于它是并发的,因此速度要快得多。所以,现在我的问题来了 - 假设我们有一个对象从代码的某个点被弱引用并且没有对该对象的强引用,这意味着我们可以像往常一样访问和使用这个对象,直到收集器不会决定收回其 space。那么,如果收集器在通过 WeakReference 访问弱引用对象的过程中尝试释放其保留的内存,会发生什么情况?我的意思是当收集器决定释放其内存时,代码在 WeakRefernce class 中“准确地”调用 get() 方法。从理论上讲,我上面描述的两种类型的 GC 技术都是可行的。由于 stop-the-world GC 会暂停应用程序 - 应用程序可能会在访问此对象时“恰好”暂停!对于并发 GC,它甚至更容易 - GC 与应用程序执行同时发生。
同样,这是一个理论问题,我不能 100% 确定它是否可能!只是想了解 Java 世界的这种边缘情况。
谢谢!
此致,
Andre

没那么容易。为了保持堆的一致性——您不会直接访问堆(至少当 GC 处于活动状态时),您可以通过典型 GC 创建的一些间接访问它。您可以将其视为 GC 世界中的“代理”——这些被称为 barriers is one example of how a certain HotSpot Collector does it, or you might want to read this also.

用非常非常简单的话说,“恰好在访问期间”,并不是恰好。对于 concurrent 循环,这将是一个原子 CAS 操作,但如果它是一个停止世界的循环——事情就简单多了。因此,您永远无法在 GC 对其执行操作的同时 确切 访问 WeakReference::get。如果您可以并且 GC 允许这样做,堆一致性将消失,您的代码工作的任何保证也将消失。

我的最后一点是,除非 google 发明(并为 处理 WeakReferences 的算法申请专利),WeakReferences(和 Soft/Phantom/Finalizer) 在完全暂停的情况下进行处理。