객체가 gc의 대상이 되어야만 작동하므로 gc 알고리즘에 따라 finalize가 언제 실행될 지 예측할 수 없음
finalizer 스레드는 일반적으로 다른 애플리케이션 스레드보다 낮은 우선순위를 가짐
⇒ 시스템의 리소스가 제한적일 때나 시스템이 높은 부하 하에 있을 때 Finalizer 스레드가 실행될 기회를 충분히 얻지 못하게 만들 수 있음
finalize 실행 중 발생한 예외는 jvm에 잡히지 않고 무시되어 뒤의 코드가 실행되지 않을 수 있음
객체 재생성
finalizer을 오버라이딩 하여 가비지 컬렉터가 객체를 수집하려는 순간 객체를 살려내 객체가 가비지 컬렉션에서 제외되도록 만드는 방식
보안 검사 우회
객체가 파괴되는 시점에 실행되는 finalizer을 통해 보안 검사를 우회하거나 민감 정보에 접근
Finalizer보다는 덜 위험하지만, 여전히 예측 불가능하고, 느리고 일반적으로 불필요함
cleaner가 해결한 finalizer 문제
제어 가능한 스레드
Cleaner는 자체적으로 관리하는 스레드를 사용하여 정리 작업을 수행하기 때문에, finalize()보다 효율적이고 관리하기 쉬움
성능
가비지 컬렉션 후에 처리해야 할 객체들을 별도의 큐에 등록해 처리하고, finalizer보다 적은 리소스를 사용함
cleaner의 문제
cleaner의 정리 작업은 객체가 가비지 컬렉터에 의해 회수된 후 비동기적으로 수행됨
→ finalizer와 마찬가지로 정리 작업의 실행 시점을 정확히 예측할 수 없음
리소스 해제 지연
→ 가비지 컬렉터가 객체를 회수하고, cleaner가 해당 작업을 수행하는 데까지 시간이 걸릴 수 있으며, 특히 리소스가 제한적인 환경에서 문제가 될 수 있음
⇒ 상태를 영구적으로 수정하는 작업에서는 절대 finalizer나 cleaner에 의존해서는 안된다!!!
ex) 데이터베이스 같은 공유 자원의 영구 락 해제
⇒ 그 대신 AutoCloseable을 구현해주고, 클라이언트에서 인스턴스를 다 쓴 후 close 메서드를 호출하자.
클라이언트가 하지 않은 자원 회수를 늦게라도 하는 것이 나은 경우
→ 심사숙고해서 사용
네이티브 피어?
→ 일반 자바 객체가 네이티브 메서드를 통해 기능을 위임한 네이티브 객체
→ 자바에서 정의되지만, 실제 구현은 자바가 아닌 네이티브 코드(c, c++ 등)로 작성됨
네이티브 피어는 자바 객체가 아니라 gc가 그 존재를 알지 못하므로 자바 피어를 회수할 때 네이티브 피어까지 회수하지 못함