为什么垃圾回收器要单独处理finalizable对象?

Why does garbage collector process finalizable objects separately?

我正在阅读 Jeffrey Richter 的书 "CLR via c#"。引用自那里:

Finalize methods are called at the completion of a garbage collection on objects that the GC has determined to be garbage. This means that the memory for these objects cannot be reclaimed right away because the Finalize method might execute code that accesses a field. Because a finalizable object must survive the collection, it gets promoted to another generation, forcing the object to live much longer than it should

有点误导我了。为什么不能立即回收 finalizable 对象?我无法理解 finalize 方法可能执行访问字段的代码的论点。什么是问题?此外,我无法理解为什么可终结对象应该移动到老一代并存储在单独的队列中(在其他终结器线程中处理)。

在我看来,最简单的方法是在完全删除之前完成对象,而无需这些额外操作。

我认为这句话说的是 "finish your unit of work stuff and kill your instance. To kill your instance you should clean up your garbage collection because of your memory."

Why cannot finalizable object be reclaimed right away? I cannot understand argument that finalize method might execute code that accesses a field. What is problem?

  1. 因为Finalize()只是对象的普通方法,所以里面的代码可能会访问对象的任何字段。

  2. 发生垃圾回收时,所有线程都被冻结。

这两点加起来就是当gc发生的时候,并不能马上执行Finalize()方法(gc期间所有线程都paused!!),而Finalize是预计在收集对象之前调用。

以上所有这些导致垃圾收集无法在对象的 Finalize() 方法被调用之前立即杀死该对象。于是gc从"death list"中取出对象(现在说对象是复活),放到一个叫"Freachable"的队列中(F”代表finalization,“reachable”表示里面的所有对象现在都不能垃圾回收,因为gc只回收对象unreachable 来自根)。

gc完成后,一个特殊的高优先级专用线程会从"Freachable"队列中取出每个条目并调用Finalize()方法,最终使该对象"garbage collectable",当然,由于第一次gc在这个Finalize()调用进程之前已经结束,所有从"Freachable"弹出的对象现在只能安排到下一次垃圾收集。

Moreover, I cannot understand why finalizable object should be moved to older generation and stored in separated queue (to be processed in other finalizer thread).

要理解这个,首先要知道generation gc model的概念。在对象从 "Freachable" 队列中弹出并再次准备好进行垃圾收集后,由于它们在前一个对象中存活下来,因此它们已被移至老年代。