(Effective Java 2/E) 107. Item 7 - Avoid finalizers

Avoid finalizers

  • 2판 제목 : 종료자 사용을 피하라
  • 3판 제목 : finalizer와 cleaner 사용을 피하라

자바는 객체의 소멸자를 제공한다.

가비지 컬렉터가 있음에도 별도로 제공하는 이유는 가비지 컬렉터가 더 이상 사용하지 않는 자원에 대한 해제가 필요하기 때문이다.

이러한 객체의 소멸자인 종료자(finalizer) 는 예측이 불가능하며, 대체로 위험하며 일반적으로 불필요한 경우가 많다.

따라서 기본적으로는 사용을 피하는 것이 권장된다.

종료자의 한 가지 단점은 즉시 실행된다는 보장이 전혀 없기 때문에 매우 긴급한 작업을 종료자안에서 처리하면 안된다.

종료자의 실행시점은 가비지 컬렉터의 알고리즘에 따라 좌우되면 이는 JVM의 구현 방식에 따라 또 다르다.

1. 성능 저하와 명시적인 종료 메서드

종료자를 사용하면 프로그램의 성능이 심각하게 하락한다.

따라서, 파일이나 스레드처럼 명시적으로 반환해야하는 자원의 경우, 똑같이 명시적인 종료 메서드(termication method) 를 하나 정의하고 호출하는 것이 좋다.

이때 주의할 점은 유효하지않음을 표현하는 private 변수 하나를 객체가 가지고 있어야 하며,

이미 종료된 객체에 대해서 호출하는 경우 예외를 던지도록 사전 작업이 필요하다.

이러한 명시적인 종료 메서드는 객체의 종료를 보장하기 위해 보통 try-finally 블록과 함께 쓰인다.

2. 종료자의 쓰임새

종료자를 절대 쓰지말아야할 것처럼 작성했지만, 두 가지의 쓰임새가 있다.

하나는 명시적인 종료 메서드의 호출을 누락했을 경우에 대비하는 안전망의 역할이다.

종료자의 호출 시점은 예상이 불가능하기때문에 점유하고 있는 자원의 반환이 늦어질 순 있겠지만, 어찌되었건 자원을 반환될 것이다.

단, 종료자가 자원을 반환하게 될 경우 명시적으로 로그를 남겨, 프로그램의 버그로 취급한 뒤 개선하는 것이 권장된다.

두번째 쓰임새는 네이티브 피어(native peer) 와 연결된 객체를 다룰 때이다.

네이티브 피어는 자바의 일반 객체가 네이티브 메서드를 통해 기능 수행을 위임하는 경우를 뜻하는데,

네이티브 피어는 일반 객체가 아니므로 가비지 컬렉터가 존재를 알지 못하며 자바 피어를 반환하는 경우에도 같이 반환되지도 않는다.

따라서 네이티브 피어가 주요 자원을 점유하지않고 있는 경우 종료자를 통해 반환시키는 것이 좋다.