【问题标题】:C# Garbage collectionC# 垃圾回收
【发布时间】:2011-11-29 03:03:53
【问题描述】:

假设我们有:

public void foo()
{
   someRefType test = new someRefType ();
   test = new someRefType ();
}

垃圾收集器如何处理第一个堆对象?是否在新分配之前立即收集垃圾?一般机制是什么?

【问题讨论】:

标签: c# garbage-collection heap-memory


【解决方案1】:

垃圾收集器如何处理第一个堆对象?

谁知道?这不是确定性的。可以这样想:在具有无限内存的系统上,垃圾收集器没有任何事情。你可能认为这是一个不好的例子,但这就是垃圾收集器为你模拟的:一个具有无限内存的系统。因为在可用内存比程序所需的足够多的系统上,垃圾收集器永远必须运行。因此,您的程序无法对何时收集内存(如果有的话)做出任何假设。

所以,您的问题的答案是:我们不知道。

在新分配之前是否立即收集垃圾?

没有。垃圾收集器不是确定性的。你不知道它什么时候会收集和释放垃圾。您不能对何时收集垃圾或何时运行终结器做出任何假设。

事实上,它不太可能被这么快收集(这会使收集过于频繁)。此外,在具有足够内存的系统上,垃圾收集器从不 必须运行。

一般机制是什么?

这是一个相当广泛的问题。但其基本原理非常简单:垃圾收集器模拟一台内存无限的机器。为此,它以某种方式跟踪内存并能够确定内存何时是垃圾。当它认为合适时,由于需要模拟无限内存,它会不时收集这些垃圾并使其再次可用于分配。

【讨论】:

  • 或者更准确地说“我们不知道”。
【解决方案2】:

不,没有任何内容表明该对象被立即收集。事实上,这不太可能。它最终会被垃圾收集器收集,但你无法确切知道何时。

您可以通过调用 GC.Collect 来强制收集,但通常不建议这样做。

垃圾回收的具体工作原理是一个相当大的主题,但是您可以read on MSDN 找到很好的文档。

【讨论】:

    【解决方案3】:

    有许多不同的垃圾收集策略,这些年来它们变得更加复杂和高效。文献和网络上有很多关于它们的优秀资源。但我也发现有时一个不完美且色彩丰富的比喻给了我一种直觉,帮助我开始。所以请允许我试一试:

    .NET 有一个所谓的“分代”垃圾收集器,我认为它的行为就像我自己一样。我让脏衣服和邮件(“C# 对象”)在我的客厅地板上堆积了几天(“内存”),当我发现我再也看不到地毯时(“内存已满” )我花了一些时间清理(“垃圾收集”)起居室(“0代”),扔掉不再需要的物品(“不再可用”)并将剩余的物品移到我的卧室( “第一代”)。很多时候,这为我争取了一些时间,我不需要再做任何工作了。但是当我的卧室填满时,我会做类似的事情,扔掉一些物品并将其他物品移到我的地下室(“第 2 代”)。有时甚至地下室也会被填满,然后我遇到了真正的问题,需要进行一些大的春季大扫除(“完整收集”)。

    将这个比喻应用到您的示例中,我们可能会猜测第一块垃圾(“堆对象”)只是闲置,直到我有时间捡起它(“运行第 0 代收集器”),当我感觉喜欢它,当地板被完全覆盖时,或者永远不会:-)

    【讨论】:

      【解决方案4】:

      要查看对象何时被删除,您可以覆盖类中的finalize 方法以打印何时以及哪些对象被删除,如下面的示例所示:

      class MyClass
      {
          private int _id;
      
          public MyClass(int id)
          {
              _id = id;
          }
      
          ~MyClass()
          {
              Console.WriteLine("Object " + _id + " deleted at " + DateTime.Now + " .");
          }
      }
      
      class Program
      {
          static void Main(string[] args)
          {
              MyClass p1 = new MyClass(1);
              p1 = new MyClass(2);
      
              Console.ReadKey();
          }
      }
      

      要强制垃圾收集器更快地释放这些对象,您可以将一个字段作为长数组添加到它们,例如 private int []memory; 并在构造函数中:memory=new int[10000000]

      【讨论】:

        猜你喜欢
        • 2021-12-20
        • 2015-06-10
        • 2010-11-01
        • 1970-01-01
        • 2012-09-01
        • 1970-01-01
        • 2011-12-21
        • 2012-01-28
        • 2013-06-27
        相关资源
        最近更新 更多