【问题标题】:Does GC guarantee that cleared References are enqueued to ReferenceQueue in topological order?GC 是否保证清除的引用按拓扑顺序排入 ReferenceQueue?
【发布时间】:2010-03-23 01:42:08
【问题描述】:

假设有两个对象,AB,并且有一个指针 A.x --> B,我们创建了一个指向 ABWeakReferences,并带有一个关联的 @ 987654328@.

假设AB 都变得无法访问。直觉上,BA 之前不能被认为是不可访问的。在这种情况下,我们是否以某种方式保证各个引用将在ReferenceQueue 中以直观(没有循环时的拓扑)顺序排队? IE。参考(A)在参考(B)之前。我不知道——如果 GC 将一堆对象标记为无法访问,然后以不特定的顺序将它们排入队列会怎样?

我正在审查Finalizer.java的番石榴,看到这个sn-p:

private void cleanUp(Reference<?> reference) throws ShutDown {
  ...
  if (reference == frqReference) {
    /*
     * The client no longer has a reference to the
     * FinalizableReferenceQueue. We can stop.
     */
    throw new ShutDown();
  }

frqReference 是对使用过的ReferenceQueue 的 PhantomReference,因此如果这是 GC'ed,则任何 Finalizable{Weak, Soft, Phantom}Reference 都不会存在,因为它们引用了队列。因此,必须先对队列本身进行 GC,然后才能对它们进行 GC - 但是,我们是否可以保证这些引用将按照它们“收集垃圾”的顺序排入 ReferenceQueue(好像它们得到 GC 一个一个)?该代码暗示存在某种保证,否则理论上未处理的引用可能会保留在队列中。

谢谢

【问题讨论】:

    标签: java reference garbage-collection guava


    【解决方案1】:

    我很确定答案是否定的。

    JVM 规范是这样描述终结器方法的:

    Java 虚拟机没有对 finalize 方法调用进行排序。终结器可以按任何顺序调用,甚至可以同时调用。 (JVM spec 2.17.7)

    由此我推断,不能保证引用按拓扑顺序排列。

    【讨论】:

      【解决方案2】:

      没有订购保证。对于 Finalizer.java,可以在处理所有引用之前关闭线程。请参阅 FinalizableReferenceQueue 的文档:

      • 保持对该对象的强引用,直到所有关联

      • 参照物已完成。如果该对象较早被垃圾回收,
      • 后备线程不会在
      • 上调用 {@code finalizeReferent()}
      • 剩余参考资料。

      这是故意行为。例如,当对键和/或值的引用被清除时,我们使用 FRQ 来清除映射条目。如果用户不再拥有对地图的引用,进而不再拥有对 FRQ 的引用,那么处理这些引用就没有意义了。

      【讨论】:

      【解决方案3】:

      我认为没有这样的保证。 GC 本身并没有完整和即时的 RAM 视图(它不能,因为 GC 在 CPU 上运行,它一次只能查看几个字节)。在您的示例中,假设一个基本的“标记和扫描”GC,很可能 A 和 B 将在同一标记阶段被声明为不可访问,并且没有特定的顺序一起扫描。维护拓扑顺序可能会很昂贵。

      至于Finalizer,它似乎只能通过FinalizableReferenceQueue 实例使用,它执行了一些与类加载器相关的魔法。 Finalizer 使用自己的设施来检测它在功能上依赖的FinalizableReferenceQueue 何时变得无法访问;这是运行Finalizer 的线程知道它应该退出的时间点。据我了解,如果应用程序让 GC 回收 FRQ,那么终结器线程将退出,并且在 FRQ 引用“之后”排队的任何引用都不会被处理。这取决于拓扑顺序或缺乏拓扑顺序,但我无法确定这是否是一个问题。我认为只要处理回收的引用对象很重要,应用程序就不应该放弃它的 FRQ。

      【讨论】:

      • 维护拓扑顺序是不可能的:如果A 引用BB 引用A 怎么办?哪个是拓扑顺序的第一个?
      • 我们只能讲无环图中的拓扑排序,请看我的原帖。
      • Thomas,(幻像)引用是对 ReferenceQueue(在 FRQ 中),而不是 FRQ 本身。除此之外,您似乎同意此代码最终可能会留下未处理的引用。唔。我会把这个转发给 Bob Lee,我怀疑还有其他诡计。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-28
      • 1970-01-01
      相关资源
      最近更新 更多