在垃圾收集期间是否调用了所有终结器?

时间:2009-12-22 18:20:40

标签: c# .net garbage-collection clr

假设我正在尝试分配100个字节,但由于我的GC堆中没有100个字节可用,因此会触发垃圾回收。此外,在我的GC堆中,有100mb的无法访问的对象。根据我的理解,一旦GC释放100字节,他就可以决定停止收集并继续执行程序。因此,假设GC没有释放50mb的物体,相当于100个不同的物体。

我的问题是:GC是否会调用终结器的全部?即使它不会删除它们? (在这种情况下,GC决定不删除的100个无法访问的对象)。

5 个答案:

答案 0 :(得分:14)

问题是这里的任何内容都可能是一个实现细节,x86 / x64 / ia64,服务器与工作站(非常不同的GC配置文件),Mono与MS .NET,操作系统版本,.NET / CLI之间可能有所不同主要版本,.NET / CLI补丁版本,Compact Framework,Micro Framework等。

我认为您不应该假设任何特定的行为,除了“具有未使用的终结器的对象可能会在某个时刻完成,但即使这样也不能保证”。

答案 1 :(得分:1)

“一旦GC释放100字节,他就可以决定停止收集” - 不,GC不会停止收集。它将始终收集第0代。如果这还不够,继续使用Gen1和Gen2 + LOB。

答案 2 :(得分:1)

.net中的垃圾收集有两个方面:终结和销毁。当创建具有终结器的对象时,它将被添加到特殊列表中,我称之为“可终结”列表。每次垃圾收集器运行时,它都会识别任何东西都无法访问的对象,只能从“可终结”列表或其中的对象访问的对象,以及可通过其他东西访问而无需通过“可终结”列表的对象。根本无法访问的对象将被销毁。那些只能从“可终结”列表或其中的对象到达的那些从该列表中删除并放入“finalize-now”列表中。可通过“可终结”列表以外的其他对象访问的对象在GC中存活。当GC将对象分类为这三个类别时,所有代码执行都将停止。 GC完成后,代码执行恢复,一个特殊的线程将开始运行“立即完成”列表中所有对象的Finalize方法。

请注意,“finalize now”列表中的对象以及由此引用的任何对象,只要它们位于该列表中,就不会被垃圾收集;他们只有在终结者运行后才有资格进行垃圾收集。一旦它们不再出现在“最终确定”列表中,它们可能再次有资格收集。

答案 3 :(得分:0)

答案是否定的。终结器运行的唯一时间是对象被销毁的时间。

答案 4 :(得分:0)

GC会多次通过。它会查找无法访问的对象,并在找到它们时检查它们是否有终结器。如果有终结器,那么它会将它们放入单独的终结器队列中,如果没有,则清除它们。所以在第一次传递时,它实际上并不调用任何终结器,它只是根据对象是否有终结器来组织对象。