2009-06-16 11 views
15

ファイナライズコール中に現在のオブジェクトへの参照を保存するとどうなりますか?例:finalize中のオブジェクトへの参照

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

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

+4

+1いい質問ですが、これはちょうど知的運動だったと思います。 ;) –

+0

心配する必要はありませんでした。 –

答えて

11

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

あなたはそれに注意する必要があり、ファイナライザはGCは、.NETのようないくつかのenviromentsに、再びそれを呼び出しませんと呼ばれたら、ファイナライザを再登録することができますが、私は、Javaについてはよく分からない

6

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

+0

Finalizeは、管理されていないリソースへの参照を解放するためにのみ使用してください。 GCは管理されたすべての参照を最終的に処理します。 –

+6

いいえ、finalizeは、任意の後で実行されるか、まったく実行されないため、使用しないでください。管理されていないリソースは、finallyブロックで明示的に解放する必要があります。最高の場合、finalize()は追加のフェイルセーフになる可能性があります。 –

+1

...しかし、フェイルセーフとしても、それは非常に問題です。それは非決定論的なので、再現可能なリソースリークを断続的なリソースリークに変えますが、発生頻度はそれほど高くありませんが、再現するのがはるかに難しくなります。そこに行って、それをやった:-(。 – sleske

1

インスタンスでは、finalize()メソッドを明示的に呼び出すことも、そのオブジェクトが占有する記憶域を再利用しようとするときにガベージコレクタによって呼び出すこともできます。

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

例外は(例えば、そのようなnullことによりbarからNullPointerExceptionとして)finalize()方法内側スローされた場合、ファイナライズ処理は単に終了します。

N.B.他の人が指摘しているように、あなたの例は間違いなく避けなければならないものです。

9

オブジェクトを完全に復活させる必要がある場合、このJavaWorldの記事では、ファイナライズされるインスタンスが再びコレクションの対象になると、ファイナライザは実行されないため、インスタンスを復活させるのではなく、再び)。

0

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を設計する場合は、機密クラスをサブクラスにすることはできません。

関連する問題