http://developers.sun.com/learning/javaoneonline/2005/coreplatform/TS-3281.html
자바의 finalize에 대한 내용입니다. 이 내용을 알면 당신도 자바 고수~
일단 상식적인 내용부터 시작하면..
1) finalize( ) 는 GC전에 호출될지 안될지 모른다. 언제 호출될지는 모른다.
2) finalize( ) 는 성능을 떨어뜨린다.
3) System.runFinalizersOnExit( )는 deprecated되었다. 가장 큰 이유는 rechable한 객체를 finalize를 하는게 말도 안된다는 것이고, 또다른 이유는 finalize의 순서가 보장안된다는데 있다.
자 다음부터 advanced된 내용입니다.
1) finalize를 실행하는 쓰레드는 애플리케이션을 실행하는 쓰레드와 별개이다. 따라서 single-threaded application에서도 synchornized가 필요할 수 있다. 이는 application과 finalize에서 동시에 xxx라는 자원을 접근한다고하면, 두개의 쓰레드가 xxx를 동시에 접근하게 된다. 이 문제를 해결하기 위해, 애플케이션의 비즈니스 로직을 담은 메소드내에서는 synchronized(xxx)를 해야하고, 물론 finalize안에서도 synchronized(xxx)를 해야합니다.
2) finalize는 어떤 메소드 foo( )내에 GC되려고 하는 객체에 대해 최종의 참조를 하고 있다면 그 시점에서 수행되버릴수 있다. 예를들어,
public long foo( … ) {
return objRef.bar();
}
와 같은 코드가 있을 때, objRef에 대한 bar( ) 호출 수행시, bar( )에서 this의 모든 final 변수만 접근가능하다고 하자. 그러면 bar( ) 호출시에 모든 final 변수를 캐싱한다음 this를 GC할 수 있다. 따라서, finalize가 this에 대해 수행될 수 있다. 만약 finalize가 수행된다면, this는 파괴된다. 그렇다면, 이 메소드는 분명히 실패할 것이다.
3) finalize는 자바 메모리 모델에 의해서 Write의 visibility만 보장한다. 이것이 의미하는 바는, Alpha와 같은 CPU를 쓰는 SMP상에서 잘못된 값을 read할 수 있다는 것이다. 따라서 제대로 된 값을 메인 메모리에서 읽어오기 위해서는 반드시 메모리 barrier를 넣어야하고, 자바에서는 베리어만 넣는 것이 불가능하므로, 어쩔 수 없이 뮤텍스를 통과시켜야한다.
결국 최종적인 ‘잘짠 finalize’는 다음과 같이 이루어진다.
void synchronized keepAlive( ) { }
public long foo( … ) {
synchornized(공유자원) { // single-thread apps 라도 반드시!
long result = objRef.bar();
}
keepAlive(); // this에 대한 최종 호출이 아니도록 만든다.
// 이를 통해 objRef.bar() 호출중 this의 파괴를 막는다.
return result;
}
protected void fiinalize() {
synchornized(this) { } // read visibility 확보
synchornized(공유자원) { // single-thread apps 라도 반드시!
자원정리
}
}
Sun Developer Network 가입자에게 (물론 가입은 무료) java one이 무료 제공됩니다. 궁금하시면 링크 따라가서 직접 세미나 보실 수 있음..