이 포스팅에서 작성하는 내용은 EFFECTIVE JAVA(이펙티브자바) 에서 발췌하였습니다.
아이템 8. finalizer와 cleaner 사용을 피하라
자바는 finalizer와 cleaner라는 두 가지 객체 소멸자를 제공한다.
이 두 가지 객체 소멸자 모두 일반적으로 불필요하다.
- finalizer : 예측할 수 없고, 상황에 따라 위험할 수 있다.
- cleaner : finalizer보다는 덜 위험하지만 여전히 예측할 수 없고 느리다.
1. finalizer와 clenaer의 단점
1. finalizer와 cleaner는 즉시 수행된다는 보장이 없기 때문에 제때 실행되어야 하는 작업은 절대 할 수 없다.
ex) 파일 닫기를 finalizer, cleaner에 맡기면 중대한 오류를 일으킬 수 있음
(시스템이 동시에 열 수 있는 파일 개수에 한계가 있는데 파일을 못닫는다면 새로운 파일을 열지 못함)
2. 수행 여부조차 보장하지 않기 때문에 상태를 영구적으로 수정하는 작업에서는 finalizer나 cleaner에 의존하면 안 된다.
ex 1) 프로세스 수 천개가 finalizer 대기열에서 회수되기만을 기다리는 데, finalizer 스레드가 다른 애플리케이션 스레드보다 우선순위가 낮아 실행조차 못하는 경우
ex 2) DB 같은 공유 자원의 영구 락 해제를 finalizer나 cleaner에 맡겨 놓으면 분산 시스템 전체가 서서히 멈춤
3. finalizer 동작 중 발생한 예외는 무시되고, 처리할 작업이 남았더라도 그 순간 종료된다.
4. finalizer를 사용한 클래스는 finalizer 공격에 노출되어 심각한 보안 문제를 일으킬 수도 있다.
생성자나 직렬화 과정에서 예외 발생 시, 생성되다 만 객체에서 악의적인 하위 클래스의 finalizer가 수행될 수 있다.
또, 객체 생성을 막으려면 생성자에서 예외를 던지는 것만으로 충분하지만, finalizer가 있다면 추가적인 작업을 해야 한다.
해결방법) final 이 아닌 클래스를 finalizer 공격으로부터 방어하려면 아무일도 하지 않는 finalizer 메서드를 만들고 final로 선언해둔다.
2. 그럼 언제 사용할까?
1) 자원의 소유자가 close메서드를 호출하지 않는 것에 대비한 안전망 역할
2) 네이티브 피어와 연결된 객체에서 사용
- 네이티브 피어 : 일반 자바 객체가 네이티브 메서드를 통해 기능을 위임한 네이티브 객체를 뜻함(GC에서 관리하지 않음)
- 성능저하를 감당할 수 있고 네이티브 피어가 심각한 자원을 가지고 있지 않을 때만 해당
- 네이티브 피어가 사용하는 자원을 즉시 회수해야할 땐 close메서드 사용
3. AutoClosable
finalizer나 cleaner 대신 AutoCloseable을 구현한 후 클라이언트에서 인스턴스를 다 쓰고 나면 close메서드를 호출.
(예외가 발생해도 제대로 종료되도록 try-with-resources를 사용하면 좋음)
'BE > Java' 카테고리의 다른 글
[Effective Java] 아이템 10. equals는 일반 규약을 지켜 재정의하라 (2) | 2022.09.11 |
---|---|
[Effective Java] 아이템 9. try-finally보다는 try-with-resources를 사용하라 (0) | 2022.09.07 |
[Effective Java] 아이템 7. 다 쓴 객체 참조를 해제하라 (0) | 2022.09.05 |
[Effective Java] 아이템 6. 불필요한 객체 생성을 피하라 (0) | 2022.09.02 |
[Effective Java] 아이템 5. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라 (0) | 2022.09.01 |