-
Item 8. finalizer와 cleaner 사용을 피하라백수의 개발/이펙티브 자바 2019. 8. 7. 16:34
finalizer와 cleaner를 피해야하는 이유
자바는 finalizer와 cleaner 두 가지 객체 소멸자를 제공한다.
finalizer는 예측할 수 없고, 상황에 따라 위험할 수 있어 일반적으로 불필요하다.
cleaner는 finalizer보다는 덜 위험하지만, 여전히 예측할 수 없고, 느리고, 일반적으로는 불필요하다.
1. 실행을 보장할 수 없다.
위 두 가지 객체 소멸자로는 즉시 수행된다는 보장이 없다.
객체에 접근할 수 없게 된 후 finalizer나 cleaner가 실행되기까지 얼마나 걸릴지 알 수 없다.
즉, 이 두 가지 객체 소멸자로는 제때 실행되어야 하는 작업은 절대 할 수 없다.
상태를 영구적으로 수정하는 적업에는 절대 finalizer나 cleaner에 의존해서는 안 된다.
2. 성능이 좋지 않다.
finalizer는 가비지 컬렉터의 효율을 떨어뜨린다. cleaner 또한 클래스의 모든 인스턴스를 수거하는 형태로 사용하면 성능은 finalizer와 비슷하다.
AutoCloseable와 finalizer를 통해 카비지 컬렉터가 수거하는 시간을 비교했을 때 finalizer가 약 50배 느린 것을 확인 할 수 있다.
3. finalizer는 보안에 취약하다.
finalizer는 생성자나 직렬화 과정에서 예외가 발생하면, 이 생성되다 만 객체에서 악의적인 하위 클래스의 finalizer가 수행 될 수 있게 된다.
또한, 정적 필드에 자신의 참조를 할당하여 가비지 컬렉터가 수집하지 못하게 막을 수 도 있다.
이러한 보안 해결책은 다음과 같다.
1.객체 생성을 막기 위해 생성자에서 예외 던지기
2. final 클래스로 만들어 하위 클래스를 만들 수 없도록 하기
3. 아무 일도 하지 않는 finalize메서드 생성 후 final로 선언
finalizer와 cleaner를 사용하는 경우는?
finalizer와 cleaner가 즉시 호출되리라는 보장은 없지만, 자원의 소유자가 cloase메서드를 호출하지 않아 자원 회수가 아예 일어나지 않는 것 보다 클라이언트가 하지 않은 자원 회수를 늦게라도 해주기 위해 사용한다.
네이티브 피어는 자바 객체가 아니라 가비지 컬렉터는 그 존재를 알지 못한다. 그 결과 자바 피어를 회수 할 때 네이티브 객체까지 회수하지 못한다. 따라서 finalizer나 cleaner로 처리하기 적절한 작업이다. 단, 성능 저하를 감당한 수 있고, 네이티브 피어가 심각한 자원을 가지고 있지 않을 때에만 해당된다.
성능 저하를 감당할 수 없거나 네이티브 피어가 사용하는 자원을 즉시 회수해야 한다면 close메서드를 사용해야 한다.
*네이티브 피어(native peer) : 일반 자바 객체가 네이티브 메서드를 통해 기능을 위임한 네이티브 객체
마무리
finalizer와 cleaner는 안전망 역할이나 중요하지 않은 네이티브 자원 회수용으로만 사용하자. 물론 이런 경우라도 불확실성과 성능 저하에 주의해야 한다.
'백수의 개발 > 이펙티브 자바' 카테고리의 다른 글
Item 10. equals는 일반 규약을 지켜 재정의하라 (0) 2019.08.13 Item 9. try-finally보다는 try-with-resource를 사용하라 (0) 2019.08.09 Item 7. 다 쓴 객체 참조를 해제하라 (0) 2019.07.19 Item 6. 불필요한 객체 생성을 피하라 (2) 2019.07.16 Item 5. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라 (0) 2019.07.15