2011-08-12 3 views
5

필자는 finalize() 메서드를 사용하여 텔레 스코핑 생성자가있는 수퍼 클래스를 사용하고 있습니다. super.finalize를 호출하는 것을 잊어 버리는 하위 클래스를 보호하기 위해 필자는 finalizer 보호자 (EJ 항목 7)를 이렇게 작성했습니다. 여기 Java finalizer 보호자가 작동하지 않는 것 같습니까?

public class Super { 

    public Super() {} 

    { 
     Object finalizerGuardian = new Object() { 
      @Override 
      protected void finalize() { 
       System.out.println("Finalizer guardian finalize"); 
       Super.this.finalize(); 
      } 
     }; 
    } 

    protected void finalize() { 
     System.out.println("Super finalize"); 
    } 

} 

은 샘플의 서브 클래스입니다 -
public class Sub extends Super { 

    public Sub() {} 

    protected void finalize() { 
     System.out.println("Sub finalize"); 
    } 

    public static void main(String[] args) 
      throws InterruptedException { 
     if (1 == 1) { 
      Sub s1 = new Sub(); 
     } 
     Runtime.getRuntime().gc(); 
     Thread.sleep(10000); 
    } 
} 

S1 객체가 범위를 벗어나

이 종료 자 보호자의 마무리()가 호출되는, 나는 서브 클래스의 Finalize 메서드에서 SYSO를 얻을, 그러나 super의 finalize에서 하나를 결코 얻지 마라.

나는 혼란 스럽다. 나는 근본적으로 무엇인가를 오해하고 있는가?

면책 조항 : finalizers는 위험하고 권장하지 않는다는 것을 알고 있습니다. 여기서도 문제를 이해하려고합니다.

답변

8

(실제 마무리를 수행 Super의 일부 메소드를 호출, 예를 들어)보다는 귀하의 경우 Super.this.finalize(); 실제로 서브 클래스에서 오버라이드 (override) 메소드를 호출 때문에 finalize() 메소드를 호출 필요한 마무리 논리 자체를 수행해야 효과적인 자바의 종료 자 보호자 .

public class Super { 
    private final Object finalizerGuardian = new Object() { 
      @Override 
      protected void finalize() { 
       Super.this.doFinalize(); 
      } 
    }; 

    private void doFinalize() { 
     System.out.println("Super finalize"); 
    } 
} 
+0

명백한 문제를보기에는 너무 효과적입니다. 감사!! – Kal

2

당신은 SubSuper.finalize() 방법을 오버로드됩니다

또한 종료 자 보호자가 클래스의 필드해야 있습니다. 그것이 호출되지 않는 이유입니다.

"finalizerGuardian"에 전화 할 때 Super.this.finalize();을 호출하면 실제로는 Sub.finalize()이 호출됩니다.

2

다른 사람들은 이미 동적 발송이 여기에 문제가되었다고 말했습니다. 하지만 코드에는 다른 주요 버그가 있습니다. finalizerGuardian은 초기화 블록 내에서만 정의됩니다. 즉, 객체가 초기화되면 객체가 범위를 벗어나 GCed 될 수 있습니다.

심지어 최종 문제를 처리하는 클래스에서 최종 메소드를 정의하여 첫 번째 문제를 해결하더라도 finalizerGuardian을 인스턴스 변수에 저장해야합니다.

2

Super.finalize()은 Sub가이를 무시하므로 호출되지 않습니다. Super._finalize() 메서드를 추가하고 Super.finalize() 및 finalizer 보호자로부터 호출 해보십시오.

또한 finalizerGuardianSuper 필드 여야합니다. 그렇지 않으면, Super 오브젝트가 여전히 강하게 도달 할지라도 가비지를 수집 할 수 있습니다.