GC 以略微不同的方式看待您的对象,并在决定什么时候回收它认为不再有用的对象时考虑到这些对象的差异。它这样做的一个方法是,它有一组根对象,用来确定哪些对象可以被回收。假如对对象的引用大体上属于如下分类中的某一个,则该引用就被看作是根:全局或静态对象指针、线程的堆栈上的所有局部变量和参数对象指针、或包含托管堆中的对象的指针的任何 CPU 寄存器。假如对象的引用是根引用,那么它可能有或可能没有与它关联的、还会在垃圾回收后幸存的子对象。GC 首先找到根对象,然后沿着引用找到被根引用的其他对象,以便避免回收这些对象。
如图 1 所示,托管堆中有四个被分配的对象:(S)mall、(L)arge、(F)inalized 和 (R)eferenced。假设每个对象通过其主要特征(例如,小型对象都不会包含引用或其他组合)来标识自己。在堆中分配这些对象时,它们将相互紧邻地放在内存中。我也有一个位于 (G)lobal 范围的根引用,它包含对 Z 的引用。
使用分析器时有几件事情要考虑到,包括线程安全和同步,以及分析器对性能的影响。Profiler API 实际上答应您将它作为 CLR 的一部分运行,这样,因为多个线程将调用您的分析器,所以您必须知道存在同步问题。Microsoft 提供的 Profiler API 规范声明:回调不会被序列化。这就需要由开发人员自己来正确保护他的代码,方法是创建线程安全的数据结构,并在一旦需要防止多个线程并行访问代码时锁定分析器代码。