Effect Java 제2판(Joshua Bloch / Addison Wesley) 을 공부하고 정리한 내용 입니다.

7. 파이널라이저(finalizer)의 사용을 피하자.

  1. 신속하게 실행된다는 보장이 없다.
    객체가 사용할 수 없게 되는 시점부터 파이널라이저가 실행되는 시점까지는 긴 시간이 소요될 수 있다. 파이널라이저 내부에서는 실행 시간이 매우 중요한 작업을 절대 하지 말아야 한다는 것이다.

  2. 파이널라이즈를 하는 동안 catch 되지 않은 예외가 발생하면 그 예외는 무시되고 그 객체의 파이널 라이즈는 종결된다.

  3. 파이널라이저를 사용하면 엄청난 성능 저하가 발생한다.

파일이나 스레드처럼 종결 작업이 필요한 자원을 갖는 객체들의 클래스에서는 파이널라이저 대신 무었을 써야 할까?
작업이나 자원을 정상적으로 종료하는 메소드만 별도로 추가하면 된다. 그리고 더 이상 필요 없는 각 인스턴스에 대해서 그 클래스의 클라이언트가 종료 메소드를 호출하도록 하면 된다.

 

파이널라이저는 어떤 경우에 사용하면 좋을까??

  1. 생성된 객체를 갖고 있는 코드에서 그 객체의 종료 메소드 호출을 빠뜨렸을 경우에 "안전망"의 역할을 하는 것이다.
    즉, 클라이언트가 종료 메소드 호출에 실패하는 그런 경우(거의 없기를 바라지만)를 대비해서 파이널라이저를 사용한다.

  2. 네이티브 피어(native peer) 객체와 관련이 있다.
    네이티브 피어는 일반 자바 객체가 아니므로, 그것과 연관된 자바 피어 객체가 소멸되면 가비지 컬렉터가 알지 못하며 재활용 할 수도 없다. 따라서 이런 경우 파이널라이저가 적합한 수단이 된다.

"파이널라이저의 연쇄 호출(chaining)" 은 자동으로 실행되지 않는다는 것에 유의하자.

 

요약

  • 종료 메소드 호출을 빼먹은 경우를 대비한 안전망의 역할이나, 또는 중요하지 않은 네이티브 자원을 종결하는 경우 외에는 파이널라이저를 사용하지 말자.
  • 어쩔 수 없이 파이널라이저를 사용해야 하는 그런 경우에는 super.finalize()를 호출하는 것을 잊지 말자.
  • 만일 안전망의 역할로 파이널라이저를 사용한다면, 부적절한 상황(자원 사요잉 끝나지 않은 객체를 파이널라이즈하는)을 메시지로 기록해야 한다는 것을 잊지 말자.
  • public 이고 final이 아닌 클래스에 파이널라이저가 필요하다면, 파이널라이저 가디언의 사용을 고려하자. 서브 클래스의 파이널라이저에서 super.finalize 호출에 실패하더라도 파이널라이즈가 될 수 있기 때문이다.
Posted by outliers
,