Finalizer & Cleaner
Finalizer와 Cleaner 사용을 피하라
Java에는 finalizer와 cleaner라는 두 가지 객체 소멸자가 존재한다.
하지만 두 소멸자 모두 예측할 수 없고, 상황에 따라 위험할 수 있기 때문에 사용을 피해야 한다.
finalizer: Java 9부터 deprecated 됨cleaner: Java 9부터finalizer를 대체하기 위해 도입되었으나 여전히 위험하고 예측할 수 없음
이 두 소멸자는 C++의 destuctor와 비슷해 보이지만, 다른 개념이기 때문에 다음과 같은 차이점이 존재한다.
- C++:
destructor는 객체의 생성을 하면 꼭 필요한 것으로 자원을 회수하는 보편적인 방법 - Java: 기본적으로 가비지 컬렉터가 자원 회수를 담당하며,
finalizer와cleaner는 즉시 수행된다는 보장이 없음
소멸자가 위험한 이유
섹션 제목: “소멸자가 위험한 이유”위에서 설명했듯이 finalizer와 cleaner는 즉시 수행된다는 보장이 없다.
위 두 소멸자의 수행 여부는 가비지 컬렉터의 알고리즘에 따라 달라지기 때문에 예측할 수 없으며 가비지 컬렉터 구현마다 다르다.
때문에 테스트 환경에서는 정상적으로 동작하지만, 프로덕션 환경에서는 예상치 못한 문제를 일으킬 수 있다.
- 즉시 수행 미보장: 가비지 컬렉터의 알고리즘에 따라 달라지기 때문에 즉시 수행되지 않을 수 있음
- 예외 처리 문제:
finalizer내부에서 발생한 예외는 무시되며, 처리할 작업이 남아있더라도 수행이 중단됨(cleaner는 해당 문제가 발생하지 않음) - 성능 문제: 가비지 컬렉터가 자동으로 수거하는 시간에 비해 훨씬 오래 걸림
- 보안 문제: 생성이 완료되지 않은 객체의 하위 클래스의
finalizer가 수행될 수 있음
finalizer와 cleaner의 사용
섹션 제목: “finalizer와 cleaner의 사용”안전망 역할
섹션 제목: “안전망 역할”만약 파일이나 스레드 등 종료해야 할 자원을 소멸시키기 위해선, 위의 두 소멸자를 사용하는 것보다 AutoCloseable 인터페이스를 구현하는 것이 더 좋다.
두 소멸자는 AutoCloseable 인터페이스의 close() 메서드를 호출하지 않는 것에 대비한 안전망 역할을 할 수 있다.
네이티브 피어
섹션 제목: “네이티브 피어”네이티브 피어란 일반 자바 객체가 네이티브 메서드를 통해 접근하는 네이티브 객체를 말한다.
네이티브 객체는 자바 객체가 아니여서 가비지 컬렉터가 회수하지 못하기 때문에 finalizer와 cleaner를 직접 사용하여 회수하는 것이 좋다.