21

finalize 呼び出し中に現在のオブジェクトへの参照を保存するとどうなりますか? 例えば:

class foo {
    ...
    public void finalize() {
        bar.REFERENCE = this;
    }
}

オブジェクトがガベージ コレクションされているかどうか。bar.REFERENCE後でアクセスしようとするとどうなりますか?

4

5 に答える 5

14

オブジェクトはガベージ コレクションされません。これは「オブジェクトの復活」として知られています。

ファイナライザーが呼び出されると、gc はそれを再度呼び出すことはありません。.NET などの一部の環境では、ファイナライザーを再登録できますが、Java についてはわかりません。

于 2009-06-16T16:27:12.727 に答える
11

どうしてもオブジェクトを復活させる必要がある場合、このJavaWorldの記事では、ファイナライズ中のインスタンスを復活させるのではなく、新しいインスタンスを作成することをお勧めします。これは、ファイナライズ中のインスタンスが再びコレクションの対象になると、単純にコレクションされる (ファイナライザーは再度実行されない) ためです。

于 2009-06-16T16:53:02.223 に答える
7

finalize()この種のことが、 の使用が一般的に推奨されない理由です。

于 2009-06-16T16:30:46.780 に答える
2

finalize()メソッドは、インスタンスで明示的に呼び出さfooれるか、ガベージ コレクターがそのオブジェクトによって占有されているストレージを再利用しようとするときに呼び出される場合があります。

barが有効なインスタンスである場合、フィールドをインスタンスに設定しREFERENCEますfoo。ガベージ コレクターの観点からは、これによりfooの参照カウントが増加します。

メソッド内で例外がスローされたfinalize()場合 (例: がNullPointerException原因でbarあるなどnull)、ファイナライズ プロセスは単純に終了します。

NB他の人が指摘したように..あなたの例は間違いなく避けるべきものです。

于 2009-06-16T16:47:31.043 に答える
2

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 を設計している場合は、機密性の高いクラスがサブクラスにならないことを確認してください。

于 2009-06-16T20:16:14.400 に答える