-
아이템8. finalizer와 cleaner 사용을 피하라책/이펙티브자바 2021. 6. 26. 18:33
자바에서는 두 가지 객체 소멸 자를 제공한다.
finalizer
- 오동작, 낮은 성능
- 예측할 수 없고 위험하여 일반적으로 불필요하다.
- 자신을 수행할 스레드를 제어할 수 없다.
- finalizer 공격에 노출되어 심각한 보안문제를 일으킬 수 있다.
- 생성자나 직렬화 과정에서 예외가 발생하면, 악의적으로 하위 클래스의 finalizer가 수행될 수도 있다.
- GC가 수집하지 못하게 막을 수 있다.
- 생성자나 직렬화 과정에서 예외가 발생하면, 악의적으로 하위 클래스의 finalizer가 수행될 수도 있다.
- 위와 같은 이유로 Java9 에서 deprecated 되었고 새로운 대안으로 cleaner를 소개한다.
cleaner
- finalizer 보다는 덜 위험하다.
- 하지만 여전히 예측할 수 없고, 느리고, 일반적으로 불필요하다.
- 자신을 수행할 스레드를 제어할 수 있다.
공통사항
- 즉시 수행된다는 보장이 없다.
- 실행되기까지 얼마나 걸릴지 알 수 가없다.
- 제때 실행되어야 하는 작업은 절대 할 수 없다.
- 심각한 성능문제를 동반한다.
- 얼마나 신속히 수행할지는 전적으로 GC 알고리즘에 달렸다.
그러면 finalizer 와 cleaner는 어디에 쓰이는가 ?
- 자원의 소유자가 close 메서드를 호출하지 않는 것에 대비한 안전망 역할
- 즉시 수행한다는 보장은 없지만 아예 안하는 것보다는 낫다.
- 라이브러리의 일부 클래스는 안전망 역할의 finalizer를 제공한다.
- ex) FileInputStream, FileOutputStream, ThreadPoolExcecutor
- 네이티브 피어 (native peer)와 연결된 객체
- 네이티브 피어 ?
- 일반 자바 객체가 네이티브 메서드를 통해서 기능을 위임한 네이티브 객체
- GC 가 자바객체가 아니니 존재를 알지 못한다.
- 회수하지 못함
- finalizer나 cleaner 가 나서서 처리하기에 적당한 작업
- 단, 성능 저하를 감당할 수 있고 네이티브 피어가 심각한 자원을 가지고 있지 않을 때에만 해당된다.
- 네이티브 피어 ?
대안
그러면 파일이나 스레드 등 종료해야 할 자원을 담고 있는 객체의 클래스에서 어떻게 해야할까 ?
- AutoCloseable을 구현하고 클라이언트에서 인스턴스를 다 쓰고 나면 close 메소드를 호출하면 된다.
- (일반적으로 예외가 발생해도 제대로 종료되도록 try-with-resource 사용이 권장된다.)
결론
cleaner는 안전망 역할이나 중요하지 않은 네이티브 자원 회수용으로만 사용한다.
물론 이런경우라도 불확실성과 성능 저하에 주의해야 한다.
'책 > 이펙티브자바' 카테고리의 다른 글
아이템10. equals는 일반 규약을 지켜 재정의하라 (0) 2021.07.02 아이템9. try-finally보다는 try-with-resources를 사용하라 (0) 2021.06.26 아이템7. 다 쓴 객체 참조를 해제하라 (0) 2021.06.23 아이템6. 불필요한 객체 생성을 피하라 (0) 2021.06.23 아이템5. 자원을 직접 명시하지말고 의존 객체 주입을 사용하라 (0) 2021.06.21