Skip to content

Finalizer & Cleaner

Finalizer와 Cleaner 사용을 피하라

Java에는 finalizercleaner라는 두 가지 객체 소멸자가 존재한다.
하지만 두 소멸자 모두 예측할 수 없고, 상황에 따라 위험할 수 있기 때문에 사용을 피해야 한다.

  • finalizer: Java 9부터 deprecated 됨
  • cleaner: Java 9부터 finalizer를 대체하기 위해 도입되었으나 여전히 위험하고 예측할 수 없음

이 두 소멸자는 C++의 destuctor와 비슷해 보이지만, 다른 개념이기 때문에 다음과 같은 차이점이 존재한다.

  • C++: destructor는 객체의 생성을 하면 꼭 필요한 것으로 자원을 회수하는 보편적인 방법
  • Java: 기본적으로 가비지 컬렉터가 자원 회수를 담당하며, finalizercleaner는 즉시 수행된다는 보장이 없음

위에서 설명했듯이 finalizercleaner는 즉시 수행된다는 보장이 없다.
위 두 소멸자의 수행 여부는 가비지 컬렉터의 알고리즘에 따라 달라지기 때문에 예측할 수 없으며 가비지 컬렉터 구현마다 다르다.
때문에 테스트 환경에서는 정상적으로 동작하지만, 프로덕션 환경에서는 예상치 못한 문제를 일으킬 수 있다.

  • 즉시 수행 미보장: 가비지 컬렉터의 알고리즘에 따라 달라지기 때문에 즉시 수행되지 않을 수 있음
  • 예외 처리 문제: finalizer 내부에서 발생한 예외는 무시되며, 처리할 작업이 남아있더라도 수행이 중단됨(cleaner는 해당 문제가 발생하지 않음)
  • 성능 문제: 가비지 컬렉터가 자동으로 수거하는 시간에 비해 훨씬 오래 걸림
  • 보안 문제: 생성이 완료되지 않은 객체의 하위 클래스의 finalizer가 수행될 수 있음

만약 파일이나 스레드 등 종료해야 할 자원을 소멸시키기 위해선, 위의 두 소멸자를 사용하는 것보다 AutoCloseable 인터페이스를 구현하는 것이 더 좋다.
두 소멸자는 AutoCloseable 인터페이스의 close() 메서드를 호출하지 않는 것에 대비한 안전망 역할을 할 수 있다.

네이티브 피어란 일반 자바 객체가 네이티브 메서드를 통해 접근하는 네이티브 객체를 말한다.
네이티브 객체는 자바 객체가 아니여서 가비지 컬렉터가 회수하지 못하기 때문에 finalizercleaner를 직접 사용하여 회수하는 것이 좋다.

Last updated:

Java