它采用了一种标记清除算法。简化版如下:首先将所有对象视为可收集的,然后扫描对象的根。任何有根的对象都被标记为正在使用中。接着,所有剩余的对象都被视为垃圾。Jeffrey Richter在CLR via C#中对细节进行了出色的描述。
这篇由A. Hunter撰写的文章(链接)讲解了所有相关内容。简而言之,GC跟随引用来查找所有不可达对象。如果一个对象或其任何超类包含另一个对象的字段,则该对象引用另一个对象。为了实现这一点,GC跟踪四种类型的根对象,称为GC根。最常见的根类型是在堆栈上创建的所有变量(正如您所猜测的那样)。其他根类型包括静态变量、Interop相关变量和带有终结器方法的对象。因此,在大多数情况下,GC会引用堆栈。