2016-06-13 7 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; 
    } 
} 

이는 IllegalStateException가 발생하지 않을 것입니다 만 GC finalize()를 호출합니다 가정, 심지어 여러 스레드의 얼굴에, 보장이 있다면?

finalize() 메서드를 사용하면 개체가 가비지 수집 가능하지 않게되므로이 개체가 가비지 수집되지 않고 다른 메서드가 호출 될 수 있습니다. 하지만이 finalize()은 그렇게하지 않습니다. foo()finalize() 이후에 호출 될 가능성이 여전히 있습니까? 그리고이 마무리 후에 사용될 수 있도록 상기 Foo 객체를 부활 할 수있다 -

+1

당신은 마무리가 된 후 '물어하셨습니까 GC에 의해 호출 되었습니까? ' 그렇지 않으면 일부 바보가 명시 적으로 호출 할 수 있습니다. – bmargulies

+0

@bmargulies 감사합니다. 실제로 그것이 의미하는 바입니다. – Owen

+0

위험을 줄이려면 Object not public에 처음 정의 된대로이 메서드를 보호해야합니다. –

답변

7

그것은 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; 
     } 
    } 
} 

: 나는이 시도/finally 블록에서() super.finalize에 대한 호출을 둘 것, 특별히 신중하기 :

@Override public void finalize() { 

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