Finalizer
는 쓰지 말자.
FinalizerExample Class
public class FinalizerExample{
@override
protected void finalize() throws Throwable{
System.cout.println("Clean Up");
}
public void hello(){
System.out.println("hello");
}
}
SampleRunner Class
public class SampleRunner{
public static void main(String[] args){
SampleRunner runner = new SampleRunner();
runner.run();
Thread.sleep(100l);
}
private void run(){
FinalizerExample finalizerExample = new FinalizerExample();
finalizerExample.hello();
}
}
실행결과
에 항상 finalize가 호출되지 않는다. 즉, finalize의 호출 여부를 보장하지 않는다는 것이다. (GC
의 대상이 되어도 즉시 수거해가지 않을 수 있다.)
인스턴스 반납을 지연 시킬 수도 있다. Finalizer는 우선 순위가 낮아서 언제 실행할지 모른다. --> OutofMemoryException이 발생할 수도 있다. Cleaner는 별도의 쓰레드로 동작하지만 여전히 해당 쓰레드는 백그라운드에서 동작하고 언제 처리될지는 알 수 없다.
성능문제가 발생한다.
AutoCloseable
객체를 만들고,try-with-resource
로 자원을 반납 하는데 걸리는 시간은 12ns이지만, Finalizer를 사용한 경우에는 550ns가 발생할 수 있다.
이상적인 해결책 -> AutoCloseable
을 사용
SampleResorce Class
public class SampleResource implements AutoCloseable{
@Override
public void close() throws RuntimeException{
System.out.println("close");
}
public void hello(){
System.cout.println("hello");
}
}
SampleRunner Class
public class SampleRunner{
public static void main(String[] args) throws InterruptedException{
/**
* 1st solution
**/
SampleReource sampleResource = null;
try{sampleResource = new SampleResource();
sampleReource.hello();
}finally{
if(sampleResource != null)
sampleResource.close();
}
}
/**
* 2st solution
**/
try(SampleResource sampleResource = new SampleResource()){
sampleResource.hello();
}
}
보안이슈 문제. Finalizer로 메모리 수거를 시도했으나, Finalizer가 실행되지 않아서 객체가 살아있을 수 있다.