.NET垃圾回收基础知识

3

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

.NET中的垃圾回收器如何识别堆上的对象是垃圾还是不是垃圾呢?

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

现在应用程序可能具有:

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

以下是我认为GC的工作方式:

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

我对我的理解正确吗?


是的,这个问题或多或少回答了我的问题。谢谢。 - Prashanth
1个回答

0

在某些情况下,你是正确的。垃圾回收器会悲观地查看堆 - 即它开始时假设所有东西(在第0代中)都将被垃圾回收。

它会通过称为“标记”的第一次扫描逐个检查堆上的每个对象,以查看是否有任何引用它。由于它们都是引用类型并且有些引用其他对象,因此它将递归地遍历这些引用。不用担心 - 它有逻辑来避免进入无限循环!

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

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

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

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

关于此主题有很多文章。我个人喜欢 Jeffrey Richter 的《CLR via C#》,他在书中给出了一个关于它如何工作的优秀章节。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接