什么是根参考?

时间:2010-05-01 08:31:44

标签: .net garbage-collection

class GCTest {
     static Object r1; 

     static void Main() {
         r1 = new Object();
         Object r2 = new Object();
         Object r3 = new Object();
         System.GC.Collect(); // what can be reclaimed here ?

         r1 = null;
         r3.ToString();
         System.GC.Collect(); // what can be reclaimed here ?
     }
    }

//代码 - DonBox的Essential .Net

6 个答案:

答案 0 :(得分:3)

在第一行,没有对r2的进一步引用,因此此对象可以在此处回收。在最后一行,为r1创建的对象不再具有引用,并且局部变量r2r3已完成,因此此时可以回收所有三个对象。但是,这将取决于它是如何编译的。

这三个都是根引用,因为没有其他内容引用它们。如果r1是实例字段而不是静态字段,那么对GCTest类的引用会使r1引用成为根引用。< / p>

答案 1 :(得分:2)

使用WeakReference尝试您的代码,当这些引用存活时,您将看到。尽量不要超出你的方法。 GC仅回收r1。当您的引用失效时,WeakReference可以为您提供更好的洞察力。

有异常的回应当然是无稽之谈。 r3.ToString()上升的唯一例外是空引用异常,但iff r3为空。

答案 2 :(得分:2)

GC可以收集它可以证明的任何对象,它对应用程序没有任何影响。考虑它的一种方法是:对象永远分配 但只要确保你不能注意到它就允许实现回收内存。

在您的示例中,在第一个GC.Collect(),第一个对象引用已写入r1r1是一个静态变量,因此不知何故“永久”。从GC的角度来看,几乎任何代码都可以使用该静态变量,因此GC无法确保不会使用第一个对象。因此无法收集它。另一方面,第二个对象是用 local 变量编写的。局部变量仅限于方法代码(当方法退出时它会消失)并且GC能够注意到r2将不再被使用(GC只需要查看方法,而不是整个代码,这是GC合理做的一部分)。因此,GC 可能收集第二个对象(此处没有义务)。

在第一个GC.Collect()之后仍将使用第三个对象:调用其ToString()方法。因此,GC不应该收集它。但是,可以想象VM注意到这是一个真实的Object实例(不是任何其他类),内联对ToString()的调用,并进一步得出结论:整个ToString()调用是一种精心制作的无所事事的方式(没有明显的结果)。因此,GC 可能能够收集第三个对象并完全跳过ToString()的呼叫。

当然,GC也可以免费收集东西。 GC的全部意义在于它“在幕后”运行,而不会影响代码执行(在最终确定的情况下这并不完全正确,但这是一个额外的复杂层,在掌握基础知识之前不应该设想)

威尔逊的article对于任何想要了解垃圾收集的人来说确实是必读的。

答案 3 :(得分:0)

对我而言,它意味着参考链中的第一个对象。即A指的是B,B指的是C等.A是根,因为没有别的指代它。

在第一个。

r1是静态的并且GC测试持有对它的引用因此无法收集,而r2可以被收集。 r3将是除非你在调试器或GC.KeepAlive被称为

在第二个

r1可以收集,因为它不再在范围内 r2已经收集完毕 并且取决于是否收集了r3,它可能会引发异常,或者会被收集。

答案 4 :(得分:0)

  • 在Main()中分配并分配给r1的对象将被跟踪,因为在r1设置为null后它无法访问。
  • r2和r3是Main()中的局部变量,因此它们是此上下文中的根。

答案 5 :(得分:0)

虽然我无法详细解答您的问题,但我可以向您指出一篇关于垃圾收集技术的好文章:

Paul R. Wilson (1994):单处理器垃圾收集技术

如果我没记错的话,它包含根引用的定义。