哪些对象有资格进行垃圾回收?

时间:2011-11-19 21:02:07

标签: c# garbage-collection weak-references

这是我最近在采访中被问到的一个问题:在'GC.Collect()'电话会议期间会收集哪些'随机'对象?

String a = new Random().Next(0, 1) ==1 ? "Whatever 1" : "Whatever 2";

String b = new WeakReference(new Random()).Target.Next(0, 1) == 1 ?
    "Whatever 1" : "Whatever 2";

GC.Collect();

我回答说这是一个特定于实现的问题,它高度依赖于GC实现和相应的弱引用语义。据我所知,C#规范没有提供GC.Collect应该做什么的准确描述以及如何处理弱引用。

但是,我的采访者想听一些其他内容。

4 个答案:

答案 0 :(得分:13)

Random()个实例和WeakReference都有资格收集:

  • 第一个Random未存储在本地,更不用说稍后读取的本地。
  • 第二个Random已传递给WeakReference,因此无论如何都可以收集 ,但WeakReference 本身没有任何地方,因此有资格收集。

没有字符串(这里只有2个字符串实例,而不是4个,即使达到了每个可能的代码路径):因为它们是c#代码中的文字,一旦存在就会被实现。

答案 1 :(得分:9)

确实这是依赖于实现(和编译器)的。如果所有这些都采用相同的方法,则无法知道哪些对象仍在堆栈中。由于堆栈上的对象仍然被引用,因此它们不可收集。

面试官希望你最有可能做的是在GC调用时检查哪些对象仍然可以访问.Collect假设一个“完美”的实现,尽快丢弃所有内容。

答案 2 :(得分:3)

  

然而,我的采访者想听别的东西。

我希望他们能够听到Marc Gravell在这里发布的答案,但这是基于过度简化的模型,该模型说明垃圾收集虚拟机的工作方式与现实无关。

例如,对GC.Collect的调用可能会优化尾调用,在这种情况下,没有全局根,因此会收集所有堆分配的块。或者编译器可能会在堆栈帧上为每个临时(不仅仅是源代码中的变量)创建一个新条目,这样可以保持一切可达,并且不会收集任何内容。或者编译器可能会交换字符串ab的创建顺序,并在Random方法之前收集WeakReference引用的Target对象被调用导致null引用异常,因此永远不会分配其他Random

答案 3 :(得分:1)

GC.Collect与Java相似,与System.gc()

相同

它“建议”检查空值以删除它们。你不能真正依赖这个功能,因为它与C ++不同,它真的很自动。

希望它有所帮助!