首先,我想让您知道,这是一个理论问题而不是实际问题,我只是好奇弱引用对象是如何被释放的。让我们快速记住 Java 中的弱引用是什么。粗略地说WeakReference
意味着当没有指向“我”的强引用时,随时释放“我”,直到“我”仍然活着。此外,我们知道有很多不同的垃圾收集器使用不同的收集技术。例如,过去 Android 是基于 Dalvik GC 的,它是 stop-the-world,字面意思是应用程序在内存清理期间暂停。后来 Dalvik 被 ART 取代——谷歌编写的新版 GC,因为它是并发的,所以速度要快得多。所以,现在我的问题来了 - 假设我们有一个从代码的某个点弱引用的对象,并且没有对该对象的强引用,这意味着我们可以像往常一样访问和使用这个对象,直到收集器无法决定收回它的空间。那么,如果收集器在通过 WeakReference
访问它的过程中试图释放这个弱引用对象保留的内存,会发生什么情况。 ?我的意思是代码调用 get()
方法来自 WeakRefernce
在收集器决定释放其内存的同时“完全”类。理论上,我上面描述的两种类型的 GC 技术都是可能的。由于 stop-the-world GC 挂起应用程序 - 应用程序可能在访问此对象时“恰好”挂起!对于并发 GC,它甚至更容易 - GC 与应用程序执行同时发生。这又是一个理论问题,我不能 100% 确定它甚至是可能的!只是想了解 Java 世界的这种边缘情况。谢谢 !问候,安德烈
最佳答案
这并不容易。为了保持堆的一致性——你不直接访问堆(至少当 GC 处于 Activity 状态时),你通过典型的 GC 创建的一些间接访问它。你可以把它想象成一个“代理”,在 GC 的世界里——它们被称为 barriers
. here是某个 HotSpot Collector 如何做到这一点的一个示例,或者您可能想阅读 this also .
用非常非常简单的话来说,“恰好在访问期间”,并不完全是。这将是一个原子 CAS
并发周期的操作,但如果它是一个停止世界的周期 - 事情要简单得多。所以你永远无法访问 WeakReference::get
在同一时间 GC 对其进行操作。如果可以并且 GC 允许这样做,那么堆一致性将消失,因此对您的代码工作的任何保证也将消失。
我的最后一点是,除非谷歌发明了(并申请了一种算法来同时处理 WeakReferences
),否则 WeakReferences
(和 Soft/Phantom/Finalizer
)在完全暂停下处理。
关于Java GC : How does Java GC clears WeakReference object?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64969727/