자바는 finalizer와 cleaner라는 두 개의 소멸자가 있다.
결론은 두 소멸자를 사용할 시 오작동, 낮은 성능, 이식성 문제의 원인이 될 수 있어 사용을 지양해야 한다.
finalizer와 cleaner는 즉시 수행된다는 보장이 없다.
finalizer를 달아두면 그 인스턴스의 자원 회수가 제멋대로 지연될 수 있다. finalizer 스레드는 다른 애플리케이션 스레드보다 우선순위가 낮아서 실행될 기회를 얻지 못할 수 있다.
cleaner는 자신을 수행할 스레드를 제어할 수 있지만 즉각 수행되라는 보장이 없다.
수행 시점 뿐만 아니라 수행 여부조차 보장받지 못한다.
System.gc, System.runFinalization 메서드가 실행 가능성을 높여줄 수 있으나, 보장은 못한다.
finalize에 발생한 예외는 무시되고 경고조차 뜨지 않는다.
cleaner는 자신의 스레드를 통제하기 때문에 이러한 문제는 발생하지 않는다.
심각한 성능 문제
gc의 효율을 떨어뜨린다.
AutoCloseable 객체를 생성하고 gc가 수거하기까지 12ns
finalizer는 550ns, cleaner 500ns
안전망 형태로 작동을 시키면 66ns
finalizer 공격에 노출 되어 심각한 보안 문제
생성자나 직렬화 과정에서 예외가 발생하면, 이 생성되다 만 객체에서 악의적인 하위 클래스의 finalizer가 수행될 수 있게 된다. 의도하지 않은 작업이 일어날 수 있기 때문에 finalizer를 사용한다면 클래스를 final로 상속을 못하도록 한다.
그럼 finalizer와 cleaner는 언제 사용하나
- 자원의 소유자가 close 메서드를 호출하지 않는 것을 대비한 안전망 역할. 즉시 호출되리라는 보장은 없지만 늦게라도 해주길 바람으로. 하지만 finalizer의 여러 단점으로 사용할 가치가 있는지 심사숙고해야 한다.
- 네이티브 피어
네이티브 피어란 일반 자바 객체가 네이티브 메서드를 통해 기능을 위임한 네이티브 객체를 말한다.
네이티브 피어는 자바 객체가 아니니 gc는 그 존재를 알지 못해 회수가 안된다. 이럴 경우 finalizer, cleaner를 사용한다.
단 성능 문제나, 심각한 자원을 가지고 있지 않을 때 사용하고, 문제가 있으면 close()를 사용해야 한다.
'Java > Effective Java' 카테고리의 다른 글
[아이템 49] 매개변수가 유효한지 검사하라 (0) | 2022.02.14 |
---|---|
[아이템 26] 로 타입(raw type)은 사용하지 말라 (0) | 2022.02.07 |
[아이템 7] 다 쓴 객체 참조를 해제하라 (0) | 2021.12.23 |
[아이템 6] 불필요한 객체 생성을 피하라 (0) | 2021.12.21 |
[아이템 5] 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라 (0) | 2021.12.20 |
댓글