垃圾收集器和循环引用

考虑这两个类:

public class A { B b; public A(B b) { this.b = b; } } public class B { A a; public B() { this.a = new A(this); } } 

如果我有像上面这样devise的课程,垃圾收集员(GC)会收集这些课程的对象吗?

假设我这样做:

 void f() { B b = new B(); } 

在这个方法中,我创build了一个名为bB实例,当方法返回时, b超出范围,GC应该能够收集它,但是如果要收集它,则必须先收集第一个哪一个是B的成员,而要收集a ,则需要先收集b这个A的成员。 它变成圆形。 所以我的问题是:这样的循环引用是为了防止GC收集对象?

  • 如果是,那么我们如何避免这个问题呢? 我们如何确保在课堂devise中没有循环引用? 是否有任何工具(或编译器选项)可以帮助我们检测循环引用?
  • 如果不是,我们在哪里以及为什么使用WeakReference类? 它的目的是什么?

.NET垃圾收集器可以绝对处理循环引用。 垃圾收集器如何工作的高层次的观点是…

  • 从本地,静态和GC固定对象开始。 这些都不能收集
  • 通过遍历这些对象的子对象来标记每个可以到达的对象
  • 收集未标记的每个对象。

这样可以很好地收集循环引用。 只要它们中的任何一个都不能从已知不可收集的对象中得到,那么循环引用本质上是不相关的。

注:我意识到我已经遗漏了很多有趣的细节,以保持简单和直接的答案

不,这不会成为问题,因为GC可以处理循环引用

MSDN说

如果一组对象包含彼此的引用,但这些对象都不是直接或间接从堆栈或共享variables引用的,则垃圾回收将自动回收内存。

几个答案已经解释说循环引用不是问题。

至于弱引用 – 使用它们的原因是caching。

当GC遍历对象依赖树时,他忽略了弱引用。 换句话说,如果一个对象的唯一引用是一个弱对象,那么它将被垃圾收集,但是如果在创build引用和尝试使用引用之间没有垃圾收集,您仍然可以访问该对象。

没有那个循环引用不会影响垃圾收集器,并且它将完全能够收集到B的实例。

垃圾收集器知道在超出范围之后,没有人可以引用B的实例,因此,没有人可以使用B的实例来间接引用A.