2

ファイナライザーはデストラクタではなく、ファイナライザーは役に立ちません。

私が聞いたところによると、多くのJavaリソースオブジェクトは「万が一に備えて」finalize()で処理します。
これは、バグにつながる可能性のある過度に寛容な態度のようです。

少なくとも、ファイナライズしてエラーをログに記録し(ファイナライズ時に未廃棄のリソース)、それらを標準出力に出力してから廃棄することをお勧めします。
より制限的な態度は、代わりに例外をどのように処理するかということかもしれません。このような制限のあるリソースオブジェクトを実装する必要はありませんが、その方法を知りたいと思います。

ただし、Javaでは、ファイナライザーでスローされた例外は無視されます(それ以外の場合、オブジェクトはリストに戻されて再度ファイナライズされます)。このようなものを実装する方法はありますか?おそらく、オブジェクトを作成したスレッドがまだ存在する場合はファイナライザーからの例外を与える方法(または存在しない場合は親スレッド?

また!!!!!他のgc言語(特にC#、pythonなど)は、リソースのファイナライズをどのように処理しますか(通常、リソースクラスの「万が一の処分」を実装しますか?)、ファイナライザーからスローし、他のスレッドに例外を与えます。(注:disposeメソッドを呼び出すために砂糖を使用したり、リソースを自動的に閉じるクロージャーを受け入れるメソッドを使用したりすることはあまり気にしません。ファイナライザーが果たす役割とファイナライザーからのエラー伝播に興味があります)。

4

2 に答える 2

1

ファイナライザーは専用スレッドで呼び出されるため、コードまたはスレッドの1つで例外をキャッチできないため、例外またはエラーをスローしても何も達成されません。

別のスレッドに例外を渡したい場合は、さまざまな方法でこれを行うことができます。ただし、別のスレッドで何をするか、現在のスレッドで何をするかは私にはわかりません。つまり、現在のスレッドにメッセージをログに記録させることができるのに、別のスレッドに渡してログメッセージに変換する例外を作成する理由。

于 2011-09-10T11:06:32.807 に答える
0

ファイナライザー自体には、オブジェクトの作成に時間がかかることから、ファイナライザースレッドがファイナライズメソッドを呼び出すまでリソースを破棄しないことなど、さまざまな欠点があります。

これを使用する必要がある唯一の理由は、リソースを破棄するための予防策を講じることです。たとえば、InputStream には close() になるメソッドがあり、これも呼び出されない可能性があります。それを使用しなければならないもう1つのケースは、ネイティブのものを使用している場合です。絶対にそれをしなければならない場合は他にありません。

上記を実装したいというあなたの願望の問題は、たとえば、 finalize() メソッドを持つオブジェクトがあるということです。オブジェクトへの強い参照がない場合、ガベージ コレクションに送信されます。次に、この特定のオブジェクトに finalize() メソッドがあるかどうかをエントリ テーブルからチェックします (オブジェクトが最初に作成されたときに記録されています)。ここで、ファイナライザ スレッドが finalize() メソッドを実行すると、このメソッド内にコード ブロックがあり、最終的にこのメソッドが強い参照を持つことになります。

次にガベージ コレクションのために同じオブジェクトが呼び出されると、このオブジェクトは 2 回目はファイナライザ キューに送信されません (デフォルトでは、どのオブジェクトも 2 回以上ファイナライザ キューに移動できないため)。したがって、2 回目は finalize() メソッドは呼び出されません。 . これは大きな問題を引き起こす可能性があります。

したがって、何かを扱っている場合は、 finalize() で行うのではなく、 finalize() メソッドの外で行うようにしてください。問題が発生するだけで、他には何もありません。

于 2011-09-10T10:45:24.203 に答える