2013-01-23 5 views
13

finalize()を使用してオブジェクトがクリーンアップされているかどうかについては、そのオブジェクトのコンストラクタが例外であるかどうかについての詳細はありますか。コンストラクタが例外をスローした後にfinalizeを呼び出すことはできますか?

このメソッドが呼び出されると、悪名高いものとして定義されます。マニュアルによると:

Javaプログラミング言語は、 任意のオブジェクトに対してfinalizeメソッドを呼び出しますどのスレッドを保証するものではありません。ただし、finalizeが呼び出されたスレッドは、finalizeが呼び出されたときにユーザーが表示できる同期ロックを保持しません。 finalizeメソッドによって 未キャッチ例外がスローされた場合、例外は が無視され、そのオブジェクトの終了が終了します。

http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#finalize%28%29

私は、このようにfinalizeメソッドをトリガーすることができていませんでした。もし誰かが呼び出されないようにするか、あるいはコンストラクタがオブジェクトの初期化に失敗した後に呼び出されるケースがあるかどうかは誰でも知っていますか?

私は2回掃除してはならないオブジェクトを持っているので、これを尋ねます。例外をスローする前にクリーンアップするのが安全かどうか、またはfinalize()のマーカーを有効にスキップして何もしないようにする必要があるかどうかを理解しようとしています。

+3

+1私はそれはあなたに別のJVMが異なる動作をする可能性があるかどうかを確認する必要があります何かあると思います。 –

+0

'finalize'を使うのは悪です。 –

+1

@Peter JLSは非常に特殊ですが、[base]オブジェクトのコンストラクタが正常に完了すると、オブジェクトはファイナライズ可能です。 –

答えて

10

私のテストは、それがJLSのセクション12.6.1. Implementing FinalizationによるJavaのHostSpotクライアントVM上1.7.0_03

+0

これはとても役に立ちます!あなたはあなたがこれを試したJVMをあなたの答えに編集できますか?私はそれを受け入れます。どうもありがとう! –

+0

これは、暗示されたsuper()が例外をスローしなかったためです。 –

7

でそれができる

public class Test1 { 

    Test1() { 
     throw new RuntimeException(); 
    } 

    @Override 
    protected void finalize() throws Throwable { 
     System.out.println("finalized"); 
    } 

    public static void main(String[] args) throws Exception { 
     try { 
      new Test1(); 
     } catch (RuntimeException e) { 
      e.printStackTrace(); 
     } 
     System.gc(); 
     Thread.sleep(1000); 
    } 
} 

プリント

java.lang.RuntimeException 
    at test.Test1.<init>(Test1.java:13) 
    at test.Test1.main(Test1.java:24) 
finalized 

ことを示しています

オブジェクトoはそのコンストラクタがoのObjectのコンストラクタを呼び出し、その呼び出しが正常に完了するまで(つまり例外をスローせずに)、finalizableはできません。あなたのコンストラクタは、オブジェクトのコンストラクターが完了した後に例外をスローする場合

、その後、あなたのオブジェクトはファイナライズする必要があり、そうfinalize()はまだ呼び出すことができます。

Objectコンストラクタがいつ呼び出されるかを正確に示すセクション12.5. Creation of New Class Instancesのオブジェクト構築をステップバイステップした良い例があります。

+0

これは、クラスX X(){super();}で、Objectへのsuper()呼び出しが例外なく完了したことを意味します。 Objectクラスには、ガベージコレクションのためにnewによって割り当てられたヒープ割り当てを登録するグルーコードがあります。 –

1

より明確に示すために:

public class Test1 { 

    public static class LifeBoat extends RuntimeException 
    { 
     private Test1 passenger; 
     public Test1 getPassenger(){return passenger;} 
     public LifeBoat(Test1 passenger){this.passenger=passenger;} 
    } 

    Test1() { 
     super(); //once this is finished, there is an Object to GC per JLS 12.6.1. 
     throw new LifeBoat(this); 
    } 

    @Override 
    protected void finalize() throws Throwable { 
     System.out.println("finalized"); 
    } 

    public static void main(String[] args) throws Exception { 
     try { 
      new Test1(); 
     } catch (LifeBoat e) { 
      Test1 obj; 
      obj=e.getPassenger(); 
      System.out.println(obj); 
     } 
     System.gc(); 
     Thread.sleep(1000); 
    } 
} 

プリント

java.lang.RuntimeException 
    at test.Test1.<init>(Test1.java:13) 
    at test.Test1.main(Test1.java:24) 
[email protected] 
finalized 
関連する問題