finalize 呼び出し中に現在のオブジェクトへの参照を保存するとどうなりますか? 例えば:
class foo {
...
public void finalize() {
bar.REFERENCE = this;
}
}
オブジェクトがガベージ コレクションされているかどうか。bar.REFERENCE
後でアクセスしようとするとどうなりますか?
finalize 呼び出し中に現在のオブジェクトへの参照を保存するとどうなりますか? 例えば:
class foo {
...
public void finalize() {
bar.REFERENCE = this;
}
}
オブジェクトがガベージ コレクションされているかどうか。bar.REFERENCE
後でアクセスしようとするとどうなりますか?
オブジェクトはガベージ コレクションされません。これは「オブジェクトの復活」として知られています。
ファイナライザーが呼び出されると、gc はそれを再度呼び出すことはありません。.NET などの一部の環境では、ファイナライザーを再登録できますが、Java についてはわかりません。
どうしてもオブジェクトを復活させる必要がある場合、このJavaWorldの記事では、ファイナライズ中のインスタンスを復活させるのではなく、新しいインスタンスを作成することをお勧めします。これは、ファイナライズ中のインスタンスが再びコレクションの対象になると、単純にコレクションされる (ファイナライザーは再度実行されない) ためです。
finalize()
この種のことが、 の使用が一般的に推奨されない理由です。
finalize()
メソッドは、インスタンスで明示的に呼び出さfoo
れるか、ガベージ コレクターがそのオブジェクトによって占有されているストレージを再利用しようとするときに呼び出される場合があります。
bar
が有効なインスタンスである場合、フィールドをインスタンスに設定しREFERENCE
ますfoo
。ガベージ コレクターの観点からは、これによりfoo
の参照カウントが増加します。
メソッド内で例外がスローされたfinalize()
場合 (例: がNullPointerException
原因でbar
あるなどnull
)、ファイナライズ プロセスは単純に終了します。
NB他の人が指摘したように..あなたの例は間違いなく避けるべきものです。
Java は安全な言語およびプラットフォームであるため、メモリは解放されません。また、関連付けられPhantomReference
た は、それらの でキューに登録されませんReferenceQueue
。VM はfinalize
オブジェクトを 1 回だけ呼び出します。JVM Spec には素晴らしい状態図があります。
通常、ファイナライザーを使用する場合は@Override protected void finalize() throws Throwable
、API を妨害しないように、宣言をそのままにしておく必要があります。Effective Java 1st Ed のように、保護されたファイナライザを使用することをお勧めします。
ClassLoader
この特定のトリックは、Princeton のグループが信頼できないコードからカスタムを構築するために使用したときに、(とにかく、サンノゼ マーキュリーの) 見出しを打ちました。仕様は少し厳しくなりましたが (Object
コンストラクターはファイナライザーを呼び出す前に正常に実行を終了する必要があります - J2SE 5.0 で指定され、Java SE 6 で実装されています)、これは依然として問題の領域です。API を設計している場合は、機密性の高いクラスがサブクラスにならないことを確認してください。