jit编译器和clr维护一个应用程序根列表,该列表指向堆中的对象或为null。 GC从这些根中创建了一个图形,并标记了该图中引用的堆中的所有对象 - 其余的都是垃圾 我的问题是:根是如何变为空的? 显而易见的情况是在代码中明确地将变量设置为null。 但如果不是呢? jit / clr如何知道何时将root设置为null?
答案 0 :(得分:1)
我的理解是应用程序根中包含的指针不是设置为null。这有点违反直觉(恕我直言),因为它看起来像处理对象的最快方式似乎是简单地摆脱它的指针,就像FAT文件系统只是标记一个FAT条目来删除文件,实际上没有跟随'指针'到磁盘上的字节并将它们设置为零。我错过了一个涉及这个问题的面试问题所以我读了一些关于它的内容,尽管它对我们每天担心的任何东西都没有任何适用性。
无论如何...... Jeffrey Richter十二年前写了一篇MSDN文章来解决这个问题。从他的文章中我了解到以下内容。
当GC运行时,它假定所有应用程序根指向无法访问的对象。它遍历根,跟随它们到堆上的对象(或发现它们没有指向任何有效的东西)。它以递归方式执行此操作,构建可到达对象的新图形。然后它走遍堆,移动有效对象并修复它们的指针 - 其效果是巩固堆顶部的空闲内存。在此过程中的某个时刻,可到达对象的图形将被复制回应用程序根目录,从而替换它们。我不确定这是在堆压缩之前还是之后发生的。
MSDN杂志12月12日和1月13日的期刊中还有一篇关于C#内存管理的文章。我没看过,但计划 - 它可能会澄清所有这些。