이펙티브 자바 8

Cleaner, Finalizer

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();
    }
    

}

단점 1

실행결과에 항상 finalize가 호출되지 않는다. 즉, finalize의 호출 여부를 보장하지 않는다는 것이다. (GC의 대상이 되어도 즉시 수거해가지 않을 수 있다.)

단점 2

인스턴스 반납을 지연 시킬 수도 있다. Finalizer는 우선 순위가 낮아서 언제 실행할지 모른다. --> OutofMemoryException이 발생할 수도 있다. Cleaner는 별도의 쓰레드로 동작하지만 여전히 해당 쓰레드는 백그라운드에서 동작하고 언제 처리될지는 알 수 없다.

단점3

성능문제가 발생한다. 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();
    }
}

단점4

보안이슈 문제. Finalizer로 메모리 수거를 시도했으나, Finalizer가 실행되지 않아서 객체가 살아있을 수 있다.

좋은 웹페이지 즐겨찾기