循环引用对象的垃圾回收

6
假设我有两个对象——对象A和对象B。对象A引用对象B,对象B引用对象A。
  1. 如果对象A和对象B都不在代码的引用范围内,垃圾收集器如何知道可以回收它们。
  2. 垃圾收集器如何推断任何对象已经超出了作用域/准备好进行垃圾回收?
  3. 如果对象A没有被我们的代码引用,但仍然可以独立存在怎么办?例如如果它是一个窗体类,即使对象A重新初始化为新实例或指定为空,它也可以自行运行。

1
你应该阅读这个链接:http://msdn.microsoft.com/en-us/library/ee787088.aspx 它可以回答你的问题并提供更多信息。(大致上,垃圾收集器有一个列表,其中包含它知道是活动的东西(静态引用、堆栈变量等),这些是“根”。通过从这些根开始遍历引用可以到达的任何其他对象也被认为是活动的。任何无法到达的对象都被视为可回收的。) - dlev
我已经编辑了你的标题。请参考“问题的标题应该包含“标签”吗?”,在那里达成共识是“不应该”。 - John Saunders
1
如果你对这种东西感兴趣,我认为(在我看来)最好的书是CLR Via C# (现已出版第四版,并更新了有关垃圾收集器的部分)。我无法高度推荐它。它真的很好地解释了CLR中正在发生的事情。 - Matthew Watson
2个回答

6
  1. 垃圾回收器不会选择一个对象并查看是否有任何引用它的东西;只有当它知道该对象是“活”的时,垃圾回收器才会保留它。垃圾回收器拥有每个它知道是“活”的对象的集合。这个集合一开始是所有静态变量、堆栈上的所有变量和一些其他特殊情况。然后,它遍历每个“活”的对象并查看它们引用了哪些对象。每个被引用的对象本身都被标记为“活”,因为这意味着它可以通过另一个“活”对象到达。它重复这个过程,直到没有发现新的对象。任何没有被标记为“活”的对象都被认为是不可达的。正如您所看到的,由于您从未检查任何给定的“死”对象引用了什么,因此循环引用是否存在并不相关。

  2. 参见#1。

  3. 好吧,在大多数情况下,实际上它确实被某个地方引用;例如,在表单的情况下,您有Application.OpenForms 引用任何打开的表单。类似的构造通常适用于这些对象。在计时器等对象的罕见情况下,它们明确地被告知不要被收集。这种情况非常罕见,通常您不需要担心。


0
  1. 垃圾回收器会查找活动引用,任何未被发现的内容都可以被回收。这样,两个对象相互引用也不会有问题,因为这些引用都是非活动的。

  2. 见1。

  3. 表单是一个组件,因此通过注册作为组件来保持其活动状态。一旦初始化,应用程序本身会保持其活动状态,直到表单被处理。将引用表单的变量设置为null只会更改引用,而不会对对象本身进行任何操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接