問題は、GC の設計が、すべてが死んでいると想定し、生きているオブジェクトを見つけてから、残りを収集することです。あなたのアイデアを機能させるには、アプローチを逆にして、すべてが生きている状態で GC を開始し、死んだオブジェクトを見つける必要があります。
このシナリオを考えてみましょう。オブジェクト A があります。これは、特別な「グラフをナビゲートしない」オブジェクトです。グラフは A->B->C になります。ライブ オブジェクトを検出する GC では、「グラフをナビゲートしない」フラグによって B と C が検出されなくなるため、B と C がアクティブであることを知る方法がありません。集めます。良くない。
では、なぜ GC は死んだオブジェクトではなく、生きているオブジェクトを検索するのでしょうか? 生きているオブジェクトを見つけるために、GC はまだ使用中であることがわかっている参照 (ルートと呼ばれる) から開始します。これらは通常、スタック上にある参照 (現在実行中のメソッドのローカル変数)、静的参照、およびその他のいくつかです。これらのルートによって参照され、グラフの最後まで再帰的にトレースされるすべてのオブジェクトは、確実にまだ使用されており、収集できません。それ以外はすべてゴミです。
逆のアプローチを実装し、すべてが生きていると仮定し、死んだオブジェクトを検索しようとした場合、ヒープ内のすべてのオブジェクトを見て、それを参照しているオブジェクトを見つけ、そのグラフがなくなるか見つかるまで追跡する必要があります。ルート。ルートが見つかった場合、チェーン内のすべてが生きています。そうでない場合、チェーン内のすべてが死んでいます。
2 つのアプローチの違いは、根から始める方がはるかに少ない作業で済むことです。あなたがフォローするすべての参照は生きていることが保証されています。オブジェクトは他の何千ものオブジェクトを参照しているかもしれませんが、そのオブジェクトと千のオブジェクトが生きていることを証明するには、ルートから 1 回通過するだけで済みます。逆に、ルートからそのオブジェクトにたどり着かない場合は、それらの何千もの参照をナビゲートすることなく、そのオブジェクトが死んでいることがわかります。
また、オブジェクトは、それらを参照するものではなく、参照するものを保存します。オブジェクトが与えられた場合、誰かがそれを参照しているかどうかを調べるには、他のすべてのオブジェクトの参照を検索する必要があります。または、各オブジェクトにレフリーのリストを保存することもできますが、各参照には 2 倍のメモリが必要です。
.Net には、ルートとして扱われる参照を作成できる GCHandle クラスがあります。したがって、オブジェクトのサブグラフは収集されません。ただし、これらのオブジェクトが何であるかを知るには、サブグラフをナビゲートする必要があります。
つまり、GC はシンプルさとパフォーマンスのためにこのように設計されています。オブジェクトのサブグラフをマーク/スイープしないと、サブグラフ内のオブジェクトがガベージ コレクションされる可能性があります。これはあなたが望むものの反対です。