2016-06-13 5 views
4

私はfinalize()の後に他のメソッドを呼び出せますか?

public class Foo { 
    private boolean finalized = false; 

    public void foo() { 
     if (finalized) 
      throw new IllegalStateException("finalize() has been called."); 
    } 

    @Override public void finalize() { 
     super.finalize(); 
     finalized = true; 
    } 
} 

を持っている場合は、それが唯一のGCはIllegalStateExceptionがスローされないことを、finalize()を呼び出しますと仮定して、でも複数のスレッドの顔には、保証されていますか?

私は、finalize()メソッドでオブジェクトをガベージコレクトできないようにする方法では、オブジェクトがガベージコレクションされず、他のメソッドが呼び出されることがあります。しかし、このfinalize()はそれをしません。 finalize()の後にまだfoo()が呼び出されている可能性はありますか?

+1

あなたは」、依頼するもしかしてGCによって呼び出されましたか?それ以外の場合、馬鹿は明示的にあなたに呼び出すことができます。 – bmargulies

+0

@bmarguliesありがとう、それは実際に私が意味していたものです。 – Owen

+0

リスクを制限するには、このメソッドをObject not publicに最初に定義されたとおりに保護する必要があります –

答えて

7

Fooのインスタンスへの参照を持っていた異なるオブジェクトが同時に確定されていることを完全に可能である - それはファイナライズ後に使用できるように、Fooオブジェクトを復活させることができます。これはちょっと失礼ですが、確かに起こることがあります。

であっても復活せず、他のファイナライザはそのファイナライザからFoo.foo()を呼び出すことができます:ジョンスキートが述べたように

public class Bar { 
    private final Foo foo; 

    @Override protected void finalize() { 
     // The finalizer in foo may already have executed... 
     foo.foo(); 
    } 
} 
0

は、それが一つのスレッドがあなたのファイナライズプロセスに現在ある間、メソッドが呼び出さ取得するために完全に可能です。

これを防ぐには、確実にコードをスレッドセーフにすることができます。

public class Foo { 
    private boolean finalized = false; 

    public void foo() { 
     synchronized (this) 
     { 
      if (finalized) 
       throw new IllegalStateException("finalize() has been called."); 
     } 
    } 

    @Override public void finalize() { 

     synchronized (this) 
     { 
      super.finalize(); 
      finalized = true; 
     } 
    } 
} 

:余分な慎重であるために、私は(super.finalizeの呼び出しを置く)のtry/finallyブロックで:ファイナライズが持っている後

@Override public void finalize() { 

     synchronized (this) 
     { 
      try 
      { 
       super.finalize(); 
      } 
      finally 
      { 
       finalized = true; 
      } 
     } 
    } 
関連する問題