假设一个对象有一个Finalize()
方法。
首次创建时,在终结队列中添加了一个指针。
该对象没有引用。
当垃圾回收发生时,它将引用从终结队列移动到 f-reachable 队列,并启动一个线程来运行该Finalize
方法(依次在其他对象的Finalize
方法之后)。
所以现在的对象(复活后)只有一个根,它是来自 f-reachable 队列的指针。
此时,对象是否/是否被提升到下一代?
假设一个对象有一个Finalize()
方法。
首次创建时,在终结队列中添加了一个指针。
该对象没有引用。
当垃圾回收发生时,它将引用从终结队列移动到 f-reachable 队列,并启动一个线程来运行该Finalize
方法(依次在其他对象的Finalize
方法之后)。
所以现在的对象(复活后)只有一个根,它是来自 f-reachable 队列的指针。
此时,对象是否/是否被提升到下一代?
这是你可以尝试的。在没有附加调试器的情况下在发布版本中运行此代码:
using System;
class Program {
static void Main(string[] args) {
var obj = new Foo();
// There are 3 generations, could have used GC.MaxGeneration
for (int ix = 0; ix < 3; ++ix) {
GC.Collect();
GC.WaitForPendingFinalizers();
}
Console.ReadLine();
}
}
class Foo {
int attempt = 0;
~Foo() {
// Don't try to do this over and over again, rough at program exit
if (attempt++ < 3) {
GC.ReRegisterForFinalize(this);
Console.WriteLine(GC.GetGeneration(this));
}
}
}
输出:
1
2
2
所以它停留在它被集合移动到的那一代,移动到每个集合的下一个,直到它到达最后一个。一般来说,这是有道理的。
似乎答案是肯定的,这会发生。http://msdn.microsoft.com/en-us/magazine/bb985010.aspx说:
... 需要两次 GC 来回收需要终结的对象使用的内存。实际上,可能需要两个以上的集合,因为对象可能会被提升到老一代。