finalizer란?
finalizer는 finalize 메소드를 오버라이드하여 Garbage Collect 대상이 될 때 수행된다. 자바 9부턴 deprecated 되었고, Cleaner를 대안으로 지정한다.
finalizer 구현
@Override
public void finalize() {
// ...
}
Java
복사
cleaner 구현
Cleaner 가 더 이상 사용되지 않을 때 등록된 스레드에서 정의된 클린 작업을 수행한다.
public class CleaningRequiredObject implements AutoCloseable {
private static final Cleaner cleaner = Cleaner.create();
private static class CleanData implements Runnable {
@Override
public void run() {
// 여기서 클린 작업 수행
}
}
private final CleanData;
private final Cleaner.Cleanable cleanable
public CleaningRequiredObject() {
this.cleanData = new CleanData();
// 등록
this.cleanable = cleaner.register(this, state);
}
@Override
public void close() {
cleanable.clean();
}
}
Java
복사
책에선 예측 불가능하고, 자주 위험하며, 일반적으로 쓸모없기 때문에 사용하지 말라고 한다. (cleaner도!)
finalizer 또는 cleaner를 쓰면 안 되는 이유
1.
자바는 finalizer의 수행 시점은 물론 수행 여부조차 보장해주지 않는다.
2.
try-with-resources 문에 비해 심각한 성능 저하가 있다.
그래서 기본적으로 '쓰지 말라고' 가이드한다.
그래도 쓸 곳 없을까요?
1.
클라이언트가 close 메소드를 호출하지 않을 경우를 대비한 안전망 역할이다.
finalizer 또는 cleaner가 동작할거란 보장은 없지만, 아무것도 안하는 것 보단 나을 수 있다. FileInputStream, FileOutputStream, ThreadPoolExecutor는 안전망 역할의 finalizer를 제공하는 라이브러리 중 하나다.
2.
네이티브 피어와 연결된 객체에서 사용할 수 있다.
네이티브 피어는 일반 자바객체가 네이티브 메서드를 통해 기능을 위임한 네이티브 객체를 말한다. 자바 객체가 아니므로 GC는 네이티브 객체의 존재조차 모른다. 이런 상황이라면 finalizer 또는 cleaner가 처리할 수 있다. 그러나 성능 저하를 감수할 수 있고 네이티브 피어가 그다지 중요하지 않은 자원을 가지고 있을 때에 해당한다. 그렇지 않다면 close 메서드를 활용해야한다.
용어정리
한글명 | 영어명 |
네이티브 피어 | native peer |
지각 | tardiness |
개심, 교정 | reclaim |