【问题标题】:Garbage collection of circular referenced object循环引用对象的垃圾收集
【发布时间】:2013-05-11 19:23:33
【问题描述】:

假设我有 2 个对象 - 对象 A 和对象 B。对象 A 引用对象 B,对象 B 引用对象 A。

  1. 如果对象 A 和对象 B 都超出了代码的引用范围 - 垃圾收集器如何知道它可以被收集。
  2. 垃圾收集器如何推断任何对象超出范围/已准备好进行垃圾收集?
  3. 如果我们的代码没有引用对象 A 但仍然可以独立,那该怎么办?例如。如果它是一个 Form 类,那么即使对象 A 重新初始化为新实例或指定为 null,它也可以自行运行。

【问题讨论】:

  • 您应该阅读以下内容:msdn.microsoft.com/en-us/library/ee787088.aspx 它回答了您的问题等等。 (粗略地说:GC 有一个它知道是活动的东西的列表(静态引用、堆栈变量等),它们是“根”。通过从这些根开始遍历引用可以到达的任何其他对象也被认为是活动的。任何不能被认为有资格收集的对象。)
  • 我已经编辑了你的标题。请参阅“Should questions include “tags” in their titles?”,其中的共识是“不,他们不应该”。
  • 如果你对这类东西感兴趣,绝对最好的书 (IMO) 是CLR Via C#(这是第 4 版,并且有关于垃圾收集器的最新更新部分)。我不能高度推荐它。它确实很好地解释了 CLR 中发生的事情。

标签: c# .net garbage-collection clr


【解决方案1】:
  1. GC 不会选择对象并查看是否有任何引用它;如果确实如此,请保留它。 GC 有一个它知道是“活着”的每个对象的集合。这个集合一开始是所有静态变量、堆栈上的所有变量以及其他一些特殊情况。然后它遍历每个“活动”对象并查看它们引用的对象。每个被引用的对象本身都被标记为“活动的”,因为这意味着它可以被另一个活动的对象以某种方式访问​​。它重复这个过程,直到没有发现新的对象。任何未被标记为活动的东西都被认为是无法访问的。如您所知,由于您从未检查过任何给定的“死”对象引用了什么,因此是否存在循环引用并不相关。

  2. 参见 #1。

  3. 嗯,在大多数情况下,它实际上是在某个地方引用的;例如,在表单的情况下,您有 Application.OpenForms 引用任何打开的表单。诸如此类的对象通常存在类似的构造。在极少数情况下,诸如计时器之类的对象会被 GC 明确告知不要被收集。这种情况非常很少见,您通常无需担心。

【讨论】:

    【解决方案2】:
    1. 垃圾收集器会查看活动引用,并且可以收集从那里找不到的任何内容。这样,两个对象相互引用就无关紧要了,因为这两个引用都处于非活动状态。

    2. 见 1。

    3. 表单是一个组件,因此通过注册为一个组件来保持活动状态。一旦初始化,应用程序本身就会保持活动状态,直到表单被释放。拥有一个引用表单的变量,然后将变量设置为 null 只会更改引用,它不会对对象本身做任何事情。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-31
      • 2011-11-12
      • 1970-01-01
      • 1970-01-01
      • 2016-01-05
      • 1970-01-01
      相关资源
      最近更新 更多