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

황제낙엽 2010.10.08 15:14 조회 수 : 608 추천: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();
}

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

번호 제목 글쓴이 날짜 조회 수
203 Applet 의 모든것 황제낙엽 2011.04.01 621
202 Java Applets in HTML5 황제낙엽 2010.12.13 728
201 (Multiple Browser Supported) Java applet using XHTML 'object' tag 황제낙엽 2010.12.13 417
200 <Applet> 과 <Object> 종합 황제낙엽 2010.12.07 389
199 codebase 를 통한 autodownload 내용 황제낙엽 2010.12.07 961
198 오브젝트(object), 이미지와 애플렛(applet) 황제낙엽 2010.12.07 394
197 [Applet] Java Plug-in 1.4.2 Developer Guide 황제낙엽 2010.12.07 401
196 [Applet] Java Plugin 가이드 (OBJECT/EMBED 태그에 의한 인트라넷) 황제낙엽 2010.11.06 443
195 [Applet] Java Plugin 가이드 (HTML 컨버터를 사용한 Java Plug-in 용 Applet 태그의 변환) 황제낙엽 2010.11.06 339
194 [Applet] Java Plugin 가이드 (applet,object, 및 embed 태그의 사용) 황제낙엽 2010.11.06 441
193 [Applet] Java Plugin 가이드 (Java Plug-in 란. 지원 내용에 대해) 황제낙엽 2010.11.06 409
192 Escape special characters 황제낙엽 2010.10.28 451
191 Servlet의 각종 Listener 사용방법 및 샘플 황제낙엽 2010.10.26 406
190 ServletContext 초기화 및 소멸 황제낙엽 2010.10.26 428
» java.lang.Object 객체 소멸 - finalize() 황제낙엽 2010.10.08 608
188 Array 또는 List 의 Sort (목록 소트) 황제낙엽 2010.09.14 538
187 Class.getResource() 와 ClassLoader.getResource()의 차이점 황제낙엽 2010.06.25 551
186 Designing RMI Applications 황제낙엽 2010.06.24 2760
185 Java Node to String Conversion 황제낙엽 2010.06.10 393
184 Java SE 6 Mustang 5장 스크립팅 기능 (번역중) 황제낙엽 2010.06.10 477