6

オブジェクトにFinalize()メソッドがあるとします。

最初に作成されたときに、ファイナライズキューにポインタが追加されました。

オブジェクトには参照がありません。

ガベージコレクションが発生すると、参照がファイナライズキューからf-reachableキューに移動し、スレッドが開始されてFinalizeメソッドが実行されます(他のオブジェクトのメソッドの後に順次Finalize)。

したがって、オブジェクトは(復活後)、f-reachableキューからのポインタであるルートを1つだけ持っています。

この時点で、オブジェクトは次世代に昇格しましたか?

4

2 に答える 2

3

これはあなたがただ試すことができるものです。デバッガーを接続せずにリリースビルドで次のコードを実行します。

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

したがって、コレクションによって移動された世代にとどまり、最後のコレクションに到達するまで、各コレクションの次のコレクションに移動します。これは一般的に理にかなっています。

于 2012-10-27T20:26:16.417 に答える
1

答えはイエスのようです、これは起こります。http://msdn.microsoft.com/en-us/magazine/bb985010.aspxによると:

...ファイナライズが必要なオブジェクトが使用するメモリを再利用するには、2つのGCが必要です。実際には、オブジェクトが古い世代に昇格する可能性があるため、3つ以上のコレクションが必要になる場合があります。

于 2012-10-27T20:19:57.327 に答える