ファイナライズコール中に現在のオブジェクトへの参照を保存するとどうなりますか?例:finalize中のオブジェクトへの参照
class foo {
...
public void finalize() {
bar.REFERENCE = this;
}
}
オブジェクトがガベージコレクトされているかどうかを確認します。後でbar.REFERENCE
にアクセスしようとするとどうなりますか?
ファイナライズコール中に現在のオブジェクトへの参照を保存するとどうなりますか?例:finalize中のオブジェクトへの参照
class foo {
...
public void finalize() {
bar.REFERENCE = this;
}
}
オブジェクトがガベージコレクトされているかどうかを確認します。後でbar.REFERENCE
にアクセスしようとするとどうなりますか?
オブジェクトはガベージコレクションされません。これは「オブジェクトの復活」として知られています。
あなたはそれに注意する必要があり、ファイナライザはGCは、.NETのようないくつかのenviromentsに、再びそれを呼び出しませんと呼ばれたら、ファイナライザを再登録することができますが、私は、Javaについてはよく分からない
この種のことは、finalize()
の使用が一般的には推奨されない理由です。
Finalizeは、管理されていないリソースへの参照を解放するためにのみ使用してください。 GCは管理されたすべての参照を最終的に処理します。 –
いいえ、finalizeは、任意の後で実行されるか、まったく実行されないため、使用しないでください。管理されていないリソースは、finallyブロックで明示的に解放する必要があります。最高の場合、finalize()は追加のフェイルセーフになる可能性があります。 –
...しかし、フェイルセーフとしても、それは非常に問題です。それは非決定論的なので、再現可能なリソースリークを断続的なリソースリークに変えますが、発生頻度はそれほど高くありませんが、再現するのがはるかに難しくなります。そこに行って、それをやった:-(。 – sleske
インスタンスでは、finalize()
メソッドを明示的に呼び出すことも、そのオブジェクトが占有する記憶域を再利用しようとするときにガベージコレクタによって呼び出すこともできます。
bar
が有効なインスタンスの場合は、REFERENCE
フィールドをfoo
インスタンスに設定します。ガベージコレクタの観点からは、これはfoo
の参照カウントを増加させます。
例外は(例えば、そのようなnull
ことによりbar
からNullPointerException
として)finalize()
方法内側スローされた場合、ファイナライズ処理は単に終了します。
N.B.他の人が指摘しているように、あなたの例は間違いなく避けなければならないものです。
オブジェクトを完全に復活させる必要がある場合、このJavaWorldの記事では、ファイナライズされるインスタンスが再びコレクションの対象になると、ファイナライザは実行されないため、インスタンスを復活させるのではなく、再び)。
Javaは安全な言語とプラットフォームであるため、メモリは解放されません。また、関連付けられたPhantomReference
は、ReferenceQueue
にエンキューされません。 VMはオブジェクト上でfinalize
を1度だけ呼び出します。 JVM仕様には素晴らしい状態図があります。
通常、ファイナライザを使用する場合は、APIを妨害しないように、宣言を@Override protected void finalize() throws Throwable
のままにしてください。 「Effective Java 1st Ed」のように、保護されたファイナライザを使用することをお勧めします。
Princetonのグループが信頼できないコードからカスタムClassLoader
を作成するときに、この特定のトリックが(San Jose Mercuryのヘッドラインに)突き当たりました。仕様は若干強化されていますが(finalizerを呼び出す前にObject
のコンストラクタを正常に実行して終了する必要があります(Java SE 6で実装されているJ2SE 5.0で指定されています)、これはまだ問題の領域です。 APIを設計する場合は、機密クラスをサブクラスにすることはできません。
+1いい質問ですが、これはちょうど知的運動だったと思います。 ;) –
心配する必要はありませんでした。 –