Item 8. Finalizer & Cleaner

Finalizer와 Cleaner 사용을 피하라

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

  • finalizer: Java 9부터 deprecated 됨

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

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

  • C++: destructor는 객체의 생성을 하면 꼭 필요한 것으로 자원을 회수하는 보편적인 방법

  • Java: 기본적으로 가비지 컬렉터가 자원 회수를 담당하며, finalizercleaner는 즉시 수행된다는 보장이 없음

소멸자가 위험한 이유

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

  • 즉시 수행 미보장: 가비지 컬렉터의 알고리즘에 따라 달라지기 때문에 즉시 수행되지 않을 수 있음

  • 예외 처리 문제: finalizer 내부에서 발생한 예외는 무시되며, 처리할 작업이 남아있더라도 수행이 중단됨(cleaner는 해당 문제가 발생하지 않음)

  • 성능 문제: 가비지 컬렉터가 자동으로 수거하는 시간에 비해 훨씬 오래 걸림

  • 보안 문제: 생성이 완료되지 않은 객체의 하위 클래스의 finalizer가 수행될 수 있음

finalizercleaner의 사용

안전망 역할

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

네이티브 피어

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

Last updated

Was this helpful?