.NET 垃圾收集器基础知识

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

<分区>

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

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

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

现在应用程序可能有:

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

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

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

我的理解正确吗?

最佳答案

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

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

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

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

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

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

关于这个主题的文章很多。我个人喜欢 Jeffrey Richter 的“CLR via C#”,他提供了一个关于它如何工作的精彩章节。

关于.NET 垃圾收集器基础知识,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1090451/

相关文章:

ios - 如何为在XCode中以 Debug模式运行的iOS应用程序创建整个内存转储

ios - 重新分配 NSString 不会释放内存

c++ - 如何释放 Kiss FFT 分配的内存?

c# 线程同步 - AutoResetEvent

c# - Emgu 中的 OpenCV Bitwise_and 函数

.net - Visual Studio + TortoiseSVN够了吗?还是我也应该使用AnkhSVN插件?

vba - CopyMemory 使 Excel 应用程序崩溃

c# - 依赖 : Microsoft Word?

java - 在 Java 中访问内存的最佳方式是什么,类似于 mmap?

c++ - reinterpret_cast 的这种使用会调用未定义的行为吗?