好奇心から、ガベージコレクターが実行に失敗するか、まったく実行されない(おそらく例外が原因で)シナリオの可能性があるかどうか疑問に思っていましたか?
はいの場合、おそらく OutOfMemory/Stackoverflow 例外が発生します。その場合、例外メッセージ、スタックトレースなどを見るだけで、gc が実行に失敗するという主要な問題を特定できます。
好奇心から、ガベージコレクターが実行に失敗するか、まったく実行されない(おそらく例外が原因で)シナリオの可能性があるかどうか疑問に思っていましたか?
はいの場合、おそらく OutOfMemory/Stackoverflow 例外が発生します。その場合、例外メッセージ、スタックトレースなどを見るだけで、gc が実行に失敗するという主要な問題を特定できます。
他の人が述べているように、多くのことがGCの実行を妨げる可能性があります。FailFastは速く失敗します。建物が取り壊される前にゴミを出すのは止まりません。しかし、あなたは特に例外について尋ねました。
キャッチされない例外は実装定義の動作を生成するため、finallyブロックが実行されるかどうか、ガベージコレクションが実行されるかどうか、およびキャッチされない例外がある場合にファイナライザキューオブジェクトがファイナライズされるかどうかは実装定義です。CLRの実装は、それが発生したときに何でも実行できます。「何でも」には、「GCを実行する」と「GCを実行しない」の両方が含まれます。実際、CLRの実装は、時間の経過とともに動作を変更しました。CLRのv1.0では、ファイナライザスレッドでキャッチされなかった例外がプロセスを削除し、v2.0では、ファイナライザスレッドでキャッチされなかった例外がキャッチされ、エラーがログに記録され、ファイナライザが実行を継続します。
興味深い質問が 4 つあります。
ガベージコレクターが実行される機会を得ることなく、何かがプログラムを完全に停止させる可能性があります
システムを完全に停止させることなく、ガベージコレクターの実行を防ぐことができますか
システムを完全に停止させることなく、オブジェクトのファイナライザーの実行を防ぐことはできますか?
例外により、オブジェクトを任意の期間収集不能にすることができますか
最初のものに関しては、答えは「間違いなく」です。潜在的に起こりうる方法はたくさんあるので、ここにリストする必要はありません。
2 番目の質問に関しては、ガベージ コレクターが失敗するとプログラムが機能しなくなるため、答えは「通常はノー」です。ただし、管理対象オブジェクトを使用する部分が無期限にブロックされる可能性がある場合でも、GC で管理されるメモリを使用しないプログラムの部分を実行し続けることができる場合があります。
3 番目の質問に関しては、ファイナライザーの例外が、アプリケーション全体を強制終了することなく、他のファイナライザーの動作に干渉することが .net にありました。このような動作は .net 2.0 以降に変更されたため、ファイナライザーからスローされたキャッチされない例外は通常、プログラム全体を強制終了します。ただし、不適切に作成されたファイナライザー内で例外がスローされてキャッチされると、想定されていたすべてのクリーンアップに失敗し、質問 4 につながる可能性があります。
4 番目の質問に関しては、オブジェクトが作成されたときに自身への長期の (場合によっては静的な) 参照を確立し、クリーンアップ コードの一部としてそのような参照を破棄することは非常に一般的です。例外により、クリーンアップ コードが期待どおりに実行されない場合、オブジェクトがもはや役に立たなくても収集できなくなる可能性があります。
finally
ブロックが実行されない特定のエッジケースがあります。FailFastの呼び出しは1つのケースであり、他のケースについてはここの質問を参照してください。
このことを考えると、ブロック内で発生するリソースのクリーンアップ/ガベージコレクションが実行されない場合(特にusing
ステートメント/IDisposable
オブジェクト)があると思います。finally
より明確に言えば、次のようなものです。
try
{
//new up an expensive object, maybe one that uses native resources
Environment.FailFast(string.Empty);
}
finally
{
Console.WriteLine("never executed");
}
はい、Java では、GC が最後に実行されずにプログラムが停止する可能性がある状況がありました。ほとんどの場合、プログラムのヒープが破棄されるとすべてのメモリがクリアされるため、これは問題ありませんが、ファイナライザーが実行されていないオブジェクトの問題。これらのファイナライザーが何をするかによって、これは問題になる場合とそうでない場合があります。
プログラムがオウムのように死んでしまうため、GC の失敗を判断できるとは思えません。事後分析でデバッグできる可能性があります (適切な dbg 設定を有効にしている場合、優れた Windows デバッグ ツールとの連携に関しては、.NET は問題ありません)。