1

Soft-、Weak- 和s的文档PhantomReference都包含与以下类似的行(取自PhantomReference):

那时,它将自动清除对该对象的所有幻像引用以及对该对象可从中访问的任何其他幻像可访问对象的所有幻像引用。

让我困惑的部分是关于其他幻影可到达对象的部分。

如果我理解正确,这描述了这种情况:
对象:

  • 一个

参考:

  • ->: 强参考
  • -P->: 幻影参考
-> A
-P-> B -> A

所以由于某种原因,垃圾收集器还没有确定这B只是幻象可达的。现在,如果A变为幻像可达并且垃圾收集器检测到这一点,则需要(根据上面引用的文档)也清除对B.

文档有什么要求吗?如果其他供应商要开发 JVM,这似乎是一个相当大的负担。

4

1 回答 1

1

我们首先要注意,这句话是从软引用和弱引用的文档中复制到 Java 9 幻像引用的文档中的,以适应在该版本中所做的更改,但不适合幻像引用,所以对于软引用和弱引用,可以更好地解释其背后的基本原理。

假设您有以下情况:

(weak)→ A
(weak)→ B (strong)→ A

从技术上讲,两者AB都是弱可访问的,但我们可以通过在任一弱引用上调用get()方法来改变这一点,以检索对其所指对象的强引用。

当我们对第一个弱引用执行此操作以检索对 的强引用时A,对象B将保持弱可达,但当我们这样做以获取对 的强引用时,由于来自的强引用B,对象A也将变得强可达BA.

因此,我们有一个规则,如果对的弱引用A被清除,则必须清除对的弱引用,否则,尽管弱引用已被清除,但仍有B可能检索对Avia的强引用。并且为了安全起见,它必须以原子方式发生,因此没有可能的竞争条件允许在两个引用的清除之间检索对的引用。BAB

如前所述,这与虚拟引用的相关性较小,因为它们不允许检索引用,但没有理由对它们进行不同的处理。

这里的重点是,考虑到垃圾收集器的实际工作方式,这并不是真正的负担。他们必须遍历所有活动引用,即强可达对象,而所有没有遇到的东西,每次消除都是垃圾。所以在遍历过程中遇到弱引用时,不会遍历所指对象,而是记住引用对象。一旦完成遍历,它将遍历所有遇到的引用对象,并查看引用对象是否已被标记为可通过不同的路径到达。如果不是,则清除引用对象并将其链接以进行排队。

为了解决您的示例:

(strong)→ A
(weak)→ B (strong)→ A

在这里,B无论对 的强引用如何,都是弱可达的A。当您消除对 的强引用时AB仍然是弱可达的并且可能会被排队。形式上,A现在是弱可访问的,但是 JVM 永远不会在不检测到B弱可访问的情况下检测到它。检测A弱可达性的唯一方法是遍历从弱可达性开始的参考图B。但是没有实现这样做。垃圾收集器将简单地清除对的弱引用,仅B此而已。

于 2019-06-20T13:38:21.333 回答