假设有一个类 A 的对象 a,它持有对 B 类的另一个对象 b 的引用。这是对 b 的唯一引用。所以现在,如果所有对 a 的引用都被删除,那么 a 就准备好进行 GC。这是否意味着 b 也准备好收集垃圾了?因为,虽然 b 有一个引用(在 a 内),但它是不可访问的,因为 a 是不可访问的。
那么这个场景究竟是如何运作的呢?我的意思是垃圾收集的顺序。
假设有一个类 A 的对象 a,它持有对 B 类的另一个对象 b 的引用。这是对 b 的唯一引用。所以现在,如果所有对 a 的引用都被删除,那么 a 就准备好进行 GC。这是否意味着 b 也准备好收集垃圾了?因为,虽然 b 有一个引用(在 a 内),但它是不可访问的,因为 a 是不可访问的。
那么这个场景究竟是如何运作的呢?我的意思是垃圾收集的顺序。
一旦某个对象无法从根目录访问,它将被收集。有关 GC 根的解释,请参阅此问题。
将收集整个子图(如您所述),假设可能无法到达该子图中的任何节点。
Java(和.NET)使用标记和清除垃圾收集来处理这类问题。
基于引用计数的系统(例如 C++ 的std::shared_ptr<T>
)在循环依赖仍然无法访问的情况下可能会失败。这对 Java/.NET GC 来说不是问题。
Java GC 足够聪明,可以收集孤立对象的孤岛,尽管它们可能相互指向。因此,b
也有资格进行垃圾收集。这里要注意的一点是,尽管您有对它的引用,但从无法从程序的根目录访问b
它的意义上说,它并不存在。
这取决于GC。可以告诉 JVM 使用不同的 GC,通常使用 3 个 GC(eden、copy、markcompact)。
在任何典型的 GC中,并且在引用您描述的情况时,您所描述的情况都得到了干净的处理,两个 obj 都被收集了。分为两个阶段:首先“a”被注意到并被收集,然后“b”被注意到并被收集。同样:注意的具体方式取决于 GC。
即使对象在内部相互引用,并且它们没有来自程序的可访问引用,它们也有资格进行 GC。这里有一个很好的解释与图表here
http://www.thejavageek.com/2013/06/22/how-do-objects-become-eligible-for-garbage-collection/
这正是 GC 的重点。由于 b 无法从主线程访问,因此它将被垃圾收集。重要的不仅仅是数量。