Soft
-,Weak
-和PhantomReference
的文档都包含类似于以下内容的行(取自PhantomReference
):
那时,它将原子清除该对象的所有幻像引用以及对任何其他可从该对象到达的幻像可访问对象的幻像引用。
让我感到困惑的部分是关于其他幻影可到达的对象。
如果我正确理解,则说明此情况:
对象:
参考文献:
->
:强引用-P->
:虚拟引用-> A
-P-> B -> A
因此由于某种原因,垃圾收集器尚未确定B
仅是幻像可到达的。现在,如果A
变为幻影可达并且垃圾回收器检测到此情况,则必须(根据上面引用的文档)还清除对B
的引用。
文档为何有此要求?看来,如果其他供应商要开发JVM,那将是一个负担。
答案 0 :(得分:1)
我们首先要注意,这句话已从软性和弱性引用文档中复制到Java 9幻象引用文档中,以适应该版本中所做的更改,但不适用于幻像引用,因此对于软引用和弱引用,可以更好地解释其背后的原理。
假设您遇到以下情况:
(weak)→ A
(weak)→ B (strong)→ A
从技术上讲,A
和B
都是弱可达的,但是我们可以通过在任一弱引用上调用get()
方法来更改此值,以检索对其引用的强引用。 / p>
当我们在第一个弱引用上执行此操作以检索对A
的强引用时,对象B
将保持弱可及性,但是当我们执行此操作以获得对{{ 1}},由于从B
到A
的强引用,对象B
也将变得非常可访问。
因此,我们的规则是,如果清除了对A
的弱引用,则必须清除对A
的弱引用,否则,就有可能检索到对B
的弱引用。尽管对A
的引用很弱,但仍通过B
A
清除了。为了安全起见,它必须是原子发生的,因此没有可能的竞争条件允许在两个引用之间的间隙之间检索对B
的引用。
如前所述,这与幻像引用的关联性较小,因为它们不允许检索引用,但没有理由将它们区别对待。
这里的要点是,考虑到垃圾收集器的实际工作方式,这并不是实际的负担。它们必须遍历所有活动引用,即,高度可访问的对象以及所有未遇到的对象,都是消除的垃圾。因此,在遍历过程中遇到弱引用时,它不会遍历引用对象,但要记住引用对象。一旦完成遍历,它将遍历所有遇到的参考对象,并查看参考对象是否已标记为可通过其他路径访问。如果没有,则清除参考对象并链接以使其入队。
以您的示例为例:
(strong)→ A
(weak)→ B (strong)→ A
在这里,B
几乎无法访问,而与A
的强引用无关。当您删除对A
的强引用时,B
仍然很难到达并且可能被排队。形式上,A
现在可以弱访问,但是JVM在未检测到B
也是弱可达的情况下也永远不会检测到。检测A
弱可达的唯一方法是遍历从弱可达B
开始的参考图。但是没有实现可以做到这一点。垃圾收集器只会清除对B
的弱引用,仅此而已。