아이템8. finalizer와 cleaner 사용을 피하라
2021-05-27 00:00:00 # Effective_Java
  • 자바의 객체 소멸자 finalizer, cleaner
  • finalizer는 예측할 수 없고, 상황에 따라 위험할 수 있어 일반적으로 불필요하다.
  • cleaner도 동일하게 예측할 수 없고, 느리고, 일반적으로 불필요하다.
  • C++에서의 파괴자는 특정 객체와 관련된 자원을 회수하는 보편적인 방법으로 여기서의 소멸자와는 다른 개념이다.
  • finalizer와 cleaner로는 제때 실행되어야 하는 작업은 절대 할 수 없다. (비동기로만 동작하는 것 같다.)
  • 상태를 영구적으로 수정하는 작업에서는 절대 finalizer나 cleaner에 의존하지 말자
  • 성능 문제와 보안 문제까지 일으킨다.
  • final이 아닌 클래스를 finalizer 공격으로부터 방어하려면 아무 일도 하지 않는 finalize 메서드를 만들고 final로 선언해라

finalizer, cleaner 용도

  • 자원의 소유자가 close 메서드를 호출하지 않는 것에 대비한 안전망 역할
  • 자바 피어를 가비지 컬렉터가 회수할 때 네이티브 객체까지 회수하지 못할 때 사용됨
    • (성능 저하를 감당할 수 있고 네이티브 피어가 심각한 자원을 가지고 있지 않을 때에만)

finalizer, cleaner의 대안

  • AutoCloseable을 구현하고, 클리이언트에서 인스턴스를 다 쓰고 나면 close 메서드를 호출하면 된다. (예외가 발생해도 제대로 종료되도록 구현해야 한다.)
  • 각 인스턴스는 자신이 닫혔는지를 추적하는 것이 좋다. (close() 사용)
  • 결국 구현할 때에 Try-with-resources를 사용해서 직접 자원해제를 수동적으로 해야한다.
  • 클라이언트를 조금만 잘못 구현해도 객체의 청소가 이뤄질지 보장할 수 없는 상태가 된다.

결론

  • 웬만하면 쓸 일이 없어야겠다.
  • 만약 사용하게 되어도 대안으로 제시된 방법(p.44 ~ p.45)을 이용해서 클라이언트까지 문제없이 작성해야겠다.
  • cleaner(자바 8까지는 finalizer)는 안전망 역할이나 중요하지 않은 네이티브 자원 회수용으로만 사용하자. (불확실성과 성능 저하에 주의하면서)