일반 java.lang.Object 객체 소멸 - finalize()

황제낙엽 2010.10.08 15:14 조회 수 : 35 추천:44

sitelink1  
sitelink2  
sitelink3 http://1 
sitelink4 http://ko 
sitelink5 http://luckfellow.blog.me/90027810932 
sitelink6 http://sitelink1 

자바의 메모리 해제는 Garbage Collector(이하 GC)에 의해 수행됩니다. finalize()는 GC에 의해 호출됩니다.
java.lang.Object에 선언된 메쏘드 선언부를 살펴보겠습니다.

protected void finalize() throws Throwable { }

일단 protected입니다. 하위 클래스에서 오버라이드할 수 있는 여지를 남겨두었습니다.
throws Throwable() 부분도 눈 여겨봐야 합니다. 무슨 에러가 나면 바로 던져 버리겠다는 뜻입니다. finalize를 호출하는 것은 GC입니다. 어떤 exception이든 GC는 걍 버립니다. 따라서 finalize 실행 중 발생한 에러는 try-catch 로 감싸지 않는 한 처리할 방법이 없습니다.

finalize()는 실행된다는 보장이 없습니다. 실행이 될 수도 안 될 수도 있고 머 그렇습니다. 그래서 필수적인 로직을 포함시켜서는 안 됩니다.

예제를 한 번 봅시다.

package objectMethod.finalize;
public class AnObject {
    @Override
    protected void finalize() throws Throwable{
            System.out.println("out!!");
            new Object();
    }
}

package objectMethod.finalize;

public class Test {
    public static void main(String[] args) {
        Test test = new Test();
        test.foo();
        System.gc();
    }
    public void foo(){
        AnObject obj = new AnObject(); 
    }
}

Test.foo() 에서 AnObject의 객체가 생성됩니다. 이는 System.gc()가 호출되면, GC에 의해 처리가 됩니다. 그러므로 finalize()가 호출이 됩니다. 제 컴터의 java (sun 1.5.12) 에서는 System.gc() 부분을 지우면 finalize()가 호출되지 않더군요.

jsr-133 자바 메모리 모델의 16장에 Finalizer에 대해서 자세히 나와있습니다. finalize()는 생성자와는 달리 상위 클래스의 finalize()가 자동으로 호출되지 않습니다. 따라서

protected void finalize() throws Throwable {
    super.finalize();
    // 기타 추가 코드
}

와 같은 방법으로 명시적인 상위클래스의 finalize()를 호출해야 합니다.

언제나 그렇듯.. 이런 식으로 명식적으로 호출하는 것이 번거롭습니다. 그럴 때는 Finalizer Guardian이라는 방법을 쓰면 됩니다.(역시 jsr-133에 나옵니다.)

class Foo {
    private final Object finalizerGuardian = new Object() {
        protected void finalize() throws Throwable {
            /* finalize outer Foo object */
        }
    }
}

Foo 를 상속 받은 클래스의 인스턴스가 생기면 상위 클래스인 Foo의 객체도 생기고 하위 클래스의 인스턴스가 GC한테 제거 당할 때 상위클래스의 인스턴스도 같이 제거당하는데, 그때 또 상위 클래스의 인스턴스 변수인 finlaizerGuardinal이란 멤버 변수도 제거 대상이 되고, 여기서 finalize()가 호출됩니다.

finalize는 반드시 호출된다는 보장이 없기 때문에 필수적인 로직을 넣으면 안 됩니다. 파일 스트림이나 디비 커넥션 등을 열었을 때는 명시적으로 닫아주는 것이 좋습니다. finalize()를 이용하면 안 됩니다.

그럼 finalize()는 모하는데 쓰느냐? 혹시나 하는 로직을 넣으면 됩니다. 디비를 열고 사용자가 혹시 안 닫았으면 닫는 로직정도죠.

if(!connection.isClosed()){
    connection.close();
}

위의 예제 정도가 적당하겠습니다.

번호 제목 글쓴이 날짜 조회 수
191 Servlet의 각종 Listener 사용방법 및 샘플 황제낙엽 2010.10.26 83
190 ServletContext 초기화 및 소멸 황제낙엽 2010.10.26 75
» java.lang.Object 객체 소멸 - finalize() 황제낙엽 2010.10.08 35
188 Array 또는 List 의 Sort (목록 소트) 황제낙엽 2010.09.14 27
187 Class.getResource() 와 ClassLoader.getResource()의 차이점 황제낙엽 2010.06.25 20
186 Designing RMI Applications 황제낙엽 2010.06.24 505
185 Java Node to String Conversion 황제낙엽 2010.06.10 54
184 Java SE 6 Mustang 5장 스크립팅 기능 (번역중) 황제낙엽 2010.06.10 21
183 Java6 에서 지원하는 Scripting (번역중) 황제낙엽 2010.05.28 216
182 RMI 시작하기(2) file 황제낙엽 2010.05.27 12
181 RMI 시작하기(1) file 황제낙엽 2010.05.27 67
180 Java Remote Method Invocation (Java RMI) 황제낙엽 2010.05.27 51
179 javax.script API 관련 스크랩 (ScriptEngine, ScriptEngineManager) 황제낙엽 2010.05.25 112
178 java.util.Properties 파일 사용 예제 file 황제낙엽 2010.04.06 68
177 10진수 <-> 16진수(Hex) 변환 file 황제낙엽 2010.03.29 1225
176 ServletConfig 이용하기 황제낙엽 2010.03.15 22
175 16비트 CRC 체크용 클래스 (사용자 클래스) 황제낙엽 2010.03.14 406
174 파일을 읽어서 CRC 값을 연산하는 메서드 (java.util.zip.CRC32) 황제낙엽 2010.03.14 137
173 byte배열에 대한 CRC 를 계산하는 메서드 (java.util.zip.CRC32) 황제낙엽 2010.03.14 2166
172 java의 List와 반복문(loop), 그리고 변수 선언 위치에 대해서 황제낙엽 2010.02.17 182