【问题标题】:.NET Garbage Collector Basics [duplicate].NET 垃圾收集器基础知识 [重复]
【发布时间】:2010-11-08 14:15:08
【问题描述】:

如果这个问题的答案很琐碎,我深表歉意。但我自己仍然无法弄清楚这一点。

.NET 中的垃圾收集器如何识别堆上的哪些对象是垃圾,哪些不是?

假设一个 .NET 应用程序正在运行,并且在某个时间点发生垃圾收集(为了简单起见,我们省略了生成和终结队列)。

现在应用程序可能有:

  1. 堆栈变量指向堆上的对象。
  2. 包含堆上对象地址的寄存器。
  3. 指向堆上对象的静态变量。

这就是我假设 GC 的工作方式。

  1. 它取消引用每个这样的地址,并最终到达堆上的对象。
  2. 它将对象标记为非垃圾(通过使用同步块索引),因为某些变量仍指向它。
  3. 它对所有地址执行此操作(在大多数文章中出于某种原因称为根)
  4. 现在,由于 .NET 运行时具有每个对象的 TYPE 信息,它可以计算每个对象的大小,从而计算它占用的堆内存块。对于所有被标记的对象,它使内存块保持原样。
  5. 释放、压缩其余内存,并在必要时重新定位其他对象(并更新它们的地址)。

我的理解正确吗?

【问题讨论】:

  • 是的,这个问题更多或回答我的问题。谢谢

标签: .net memory memory-management memory-leaks garbage-collection


【解决方案1】:

在某些情况下你是对的。 GC 悲观地查看堆 - 即它假设所有内容(第 0 代)都将被 GC。

它实际上通过称为“标记”的第一次扫描来遍历堆上的所有内容,其中检查是否有任何东西引用它。由于它们都是引用类型,并且一些引用其他类型,因此它将递归地导航引用。别担心 - 有逻辑不进入无限循环!

如果它发现一个对象没有被引用,它会首先标记它,通过在对象内设置一个称为同步块索引的标志。

在遍历堆上的每个对象后,它将开始一个称为“压缩”的过程,即当它将所有剩余的对象转移到同一内存区域中时,上面的内存是空的。它将同一代的对象保持在一起,因为它们在统计上更有可能同时被取消引用。

因此,这将减少所需的内存。

垃圾收集不一定会加速您的程序,但确实允许它重新使用未使用对象占用的空间。

关于这个主题的文章很多。我个人喜欢 Jeffrey Richter 的“通过 C# 进行 CLR”,他给出了关于它如何工作的精彩章节。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-04
    相关资源
    最近更新 更多