【问题标题】:What happens during Garbage Collection if Generation 2 is filled?如果第 2 代被填满,垃圾收集期间会发生什么?
【发布时间】:2010-11-10 22:24:33
【问题描述】:

我现在正在重读CLR via C#,并且对 .NET 中的垃圾收集有一些疑问。书中,第0代被填满后,垃圾收集开始并将所有未完成的对象引用移动到第1代。

当第 1 代被填满时,也会发生同样的情况。但是当第二代被填满时会发生什么?没有其他代可以移动参考。第 2 代的规模是否被 CLR 扩大了?

【问题讨论】:

  • 不要忘记大对象(85,000 字节或更大)将从第 2 代开始。

标签: c# .net garbage-collection


【解决方案1】:

是的,如果可以的话,它将扩大第 2 代的规模。如果没有更多可用空间,您将收到OutOfMemoryException

【讨论】:

    【解决方案2】:

    不同代的垃圾收集不是关于具有特定的大小,而是关于垃圾的年龄。据我所知,每一代都没有大小限制。

    【讨论】:

      【解决方案3】:

      据我了解,只有一个堆(具有讽刺意味的是,它通常被描述为堆栈)。对象不是在第 0 代填满时被提升到第 1 代,而是在它们在集合中存活时。简而言之,引用没有“移动”,即用于标识生成结束位置的位置被移动。

      当堆接近满时,会发生一些事情:

      1. 收集每一代,从 0 开始,以 2 结束。
        • 如果第 0 代收集足够,则不会收集第 1 代和第 2 代。
        • 如果第 0 代收集不足,但第 1 代收集充足,则不会收集第 2 代。
      2. 堆被压缩(间隙被消除)
      3. 促进世代
        • 第 1 代幸存者被标记为第 2 代。
        • 第 0 代幸存者被标记为第 1 代。

      然后将在收集中幸存的对象移动到第 0 代(如果这是它们的第一个收集周期)或第 2 代(如果它们在多个收集中幸存下来)。这样做是为了提高效率,以确保我们不会不断尝试收集长寿命的对象。

      您不会以特定于生成的方式耗尽空间。 See this article 很好的解释。

      【讨论】:

      • 我不相信有任何这样的对象标签。 CLR 会跟踪不同代使用的段,因此情况正好相反。 CLR 可以通过对象在托管堆上的位置来确定对象的生成。
      • @Brian,对不起,如果我不清楚,我的意思是说运行时会跟踪每一代的结束位置,以便添加到堆“上方”的对象属于较低的一代.我确定我过于简单化了,但你是对的,没有基于每个对象的“跟踪”它是哪一代。
      • 垃圾回收在零代满的时候运行,所以我认为没有错误。
      • @spkenny,由于堆是连续的,垃圾收集在堆满时运行。在第一次收集期间,第 0 代是您的整个堆,但随着对象被移到更高的代,它们仍然会占用堆,因此第 0 代的容量实际上会“缩小”。
      猜你喜欢
      • 1970-01-01
      • 2011-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-19
      • 2014-08-08
      • 1970-01-01
      相关资源
      最近更新 更多