使用和垃圾收集

Posted

技术标签:

【中文标题】使用和垃圾收集【英文标题】:Using and Garbage Collection 【发布时间】:2009-03-17 20:28:01 【问题描述】:

您好,如果我有以下情况,请澄清一下:

using (Object1) 
create Object2

// bookmark1

Object2 会与 Object1 一起在书签 1 处被销毁吗? Object2 属于 StringReader,Object1 属于 MemoryStream。

【问题讨论】:

当我们在它的时候 - 一旦我们在书签 1 处 Object1 会被销毁,还是它只是未被引用并等待 GC 出现? See similar question here. 它将“超出范围”(与未引用相同),因此只需等待 GC 出现并稍后清理它 【参考方案1】:

在块结束时,两个对象都不会被销毁

Object1 将被Disposed,一个不同的概念; Object2 不会发生任何事情。

这两个对象都将被收集,并可能在稍后的某个时间完成。垃圾收集是不确定的 - 你不能依赖它何时会发生。

有关更多信息,请参阅 MSDN 上的 IDisposable。

【讨论】:

【参考方案2】:

using 块实际上是这样的构造的语法糖:

try

    Brush b = new SolidBrush(Color.Red);

finally

    b.Dispose();

因此,'b' 将被放置在 try 块的末尾,除非发生了超出应用程序控制范围的事情。

【讨论】:

关闭,但不完全正确。在您的代码中 b 仍在范围内,因此无法收集它,并且当块结束时您还不能重新使用该名称。 是的,我刚刚修好了。谢谢。【参考方案3】:

在块的末尾(书签 1),在您的示例中,只会释放对象 1。在文件流的情况下,这意味着流将被关闭并释放句柄,但实际的字符串对象仍将在内存中(准备好被 GC 清理)。在您的情况下, Object2 不会被释放,因此它使用的句柄仍将保持打开状态。最终,GC 会收集它,并调用它的终结器,此时它会被正确释放。

如果您希望两个对象都被正确“清理”,则它们都需要被释放,要么通过将它们包装在 using 语句中,要么手动调用 Dispose。

还有另一种可能更简洁的语法:

using (Object1 obj1 = new Object1(), Object2 obj2 = new Object2())

    // Do something with obj1 & obj2

如果你这样做,obj1 和 obj2 都将在块的末尾被 Disposed。在您的情况下,这意味着两个对象都将关闭,并且它们的句柄将被释放。然后 GC 将在以后的垃圾回收中清理它们。

详情见MSDN's page on using.

【讨论】:

【参考方案4】:

object2 将不会与 object1 一起被销毁(处置)。但是,为 using 语句创建了一个单独的范围块,因此此时 object2 确实超出了范围。它的处置只是不确定的。

此外,如果 object2 也是 IDisposable,您可以这样做:

using (object1)
using (object2)

 // bookmark1

无论如何,正常的垃圾回收规则都适用:对象的托管资源(内存)仍以正常方式处理。使用/IDisposable 只会释放非托管资源。

【讨论】:

以上是关于使用和垃圾收集的主要内容,如果未能解决你的问题,请参考以下文章

垃圾收集器

Lua垃圾收集

JVM垃圾收集器

我们来聊聊垃圾收集器中相关术语与新生代收集器

5种JVM垃圾收集器特点和8种JVM内存溢出原因

5种JVM垃圾收集器特点和8种JVM内存溢出原因