달력

5

« 2024/5 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

'GC'에 해당되는 글 1

  1. 2009.04.15 finalize method란 무엇인가?
2009. 4. 15. 16:17

finalize method란 무엇인가? Enjoy/JAVA2009. 4. 15. 16:17



finalize method란 무엇인가?

최상위 클래스인 Object클래스는 finalize라는 이름의 protected 메쏘드를 가지고 있다. 이것은 이 클래스의 객체가 가비지 콜렉션 과정에서 가지고 있던 리소스가 반환될 때 해야 할 일에 대한 정의를 가지고 있다. 물론, 이것은 사용자가 정의한 클래스에서 재정의할 수 있다. 만일 사용자의 클래스에 이 메쏘드를 재정의했다면, 그 finalize메쏘드를 객체의 Finalizer라고 부른다. 그렇다면 이것은 누가 호출하는가? 자바 가상 머신이 그 객체가 가지고 있는 메모리가 반환되기 전에 이것을 수행한다. 이 메쏘드를 재정의함으로써, 단순히 메모리를 반환하는 것 이상의 작업을 할 수 있다.  

 

여기에 대한 정의는 자바 가상 머신에 되어 있지 않다. 단순히 그 객체가 사용하고 있던 리소스가 재사용되기 전에만 실행되면 된다. 어느 쓰레드가 이 파이널라이저를 실행해야 한다는 규정도 없다. Object 클래스의 finalizer메쏘드가 하는 일은 아무 것도 없다.

또한 하위 클래스의 파이널라이저는 상위 클래스의 파이널라이저를 암시적으로 호출하지 않는다. 생성자와는 다르다. 생성자는 자신의 상위 클래스 객체의 생성자를 암시적으로 호출하게 된다. 그래서 하위 클래스의 파이널라이저는 항상 super키워드를 통해 상위 클래스의 파이널라이저를 호출하는 것이 좋다.

protected void finalize() throws Throwable {
super.finalize(); .....
}

파이널라이저의 구현

이 개념을 잡기 위해 두 종류의 애트리뷰트들을 규정하는 것이 좋겠다.

Reachability

 

  • reachable : 살아 있는 쓰레드들에 의해 지속적으로 접근될 수 있는 객체의 상태. 프로그램의 최적화는 이런 reachable한 객체의 숫자를 줄이는 방향으로 나갈 수 있다. 예를 들어, 사용자가 명시적으로 하지 않았더라도 컴파일러나 코드 생성기가 더 이상 사용되지 않을 객체의 레퍼런스에 대해 미리 null이라고 세팅함으로써, 빠른 시간 내에 가비지 수집이 될 수 있게 하는 것이다.
  • finalizer-reachable : 현재 살아있는 쓰레드들에 의해 참조되지는 않으나, finalizable한 객체들에 의해 참조되고 있는 객체의 상태.
  • unreachable : 어떠한 객체들로부터도 참조되지 않는 객체.
Finalization
 
  • unfinalized : 파이널라이저가 자동으로 수행되지 않은 객체의 상태.
  • finalizable :  파이널라이저가 자동으로 수행되지 않은 상태이지만, 자바 가상 머신이 언제라도 파이널라이저를 수행할 수 있는 객체의 상태. 즉 파이널라이저에 의해서는 참조가 되고 있는 상태
  • finalized : 파이널라이저가 자동으로 수행된 객체의 상태.

  이와 같은 두 애트리뷰트의 부류를 고려한 객체의 라이프 사이클은 다음과 같다.

 객체의 라이프 사이클

  • A : 객체가 처음 생성되었을 때에는 reachable이면서 unfinalized한 상태이다
  • 객체의 참조가 실행 도중 살아 있는 쓰레드로부터 접근할 수 없게 되면서 객체의 상태는 finalizer-reachable(B,C,D)나 unreachable(E,F)의 상태가 된다.
  • 이 그림에서 주의깊게 봐야 할 것은 f-reachable한 상태에서 직접 unreachable한 상태로 이동하지는 않는다는 것이다. 파이널라이저가 수행시작되는 순간 reachable한 상태가 되면서 unreachable상태로 이동하게 되는 것이다.
  • G,H : unfinalized상태의 객체가 f-reachable이나 unreachable상태가 된 것을 자바 가상 머신이 탐지하고 finalizable이라는 상태로 세팅한다. 그리고, 그 객체가 unreachable 상태라면 f-reachable상태로 바꾸어 파이널라이저가 수행될 수 있도록 한다.
  • I : 파이널라이저가 수행되었고 unreachable이면 이 객체는 메모리로부터 제거된다.
  • J,K : 자바 가상 머신은 finalizable한 객체에 대해서는 임의의 쓰레드를 이용해 파이널라이저를 수행시킬 수 있다. 이 경우에 객체는 finalized이면서 reachable한 상태가 된다.
  • L,M,N : 위와 같은 작업에 의해 f-reachable이었던 다른 객체들의 상태가 reachable해지게 될 수도 있다.
  • 위에서 한 가지 상태가 빠져 있다. finalizable이면서 unreachable한 상태로 이런 상태는 있을 수 없다. finaliable한 객체는 파이널라이저에 의해 접근될 수 있기 때문이다.
  • O : 파이널라이저가 정의되지 않은 사용자 클래스의 경우 굳이 복잡한 상태를 거칠 이유가 없다.
강제 가비지 콜렉션 구현의 예
 
 import java.lang.ref.*;

public class FinalizeTest {
    String oops = "Oopsla";
    static Reference weakref;

          protected void finalize() throws Throwable {
          System.out.println("Finalizer Called");
}     public static void main(String[] args) {
     FinalizeTest f = new FinalizeTest();
          Reference weakref = new WeakReference(f);

                    System.out.println("Before GC = " + weakref.get());
                     f = null;
                    Runtime rt = Runtime.getRuntime();
                    long free = rt.freeMemory();
         long oldfree;

                 do {
oldfree = free;
rt.gc();
free = rt.freeMemory();
         } while (free > oldfree);

                    System.out.println("After GC = " + weakref.get());
}
}

실행 결과
Before GC = FinalizeTest@7923b8c9
Finalizer Called
AfterGC = null

클래스 파이널라이저

  클래스가 언로딩될 때 암시적으로 호출되는 메쏘드를 다음과 같이 정의할 수 있다.

static void classFinalize() throws Throwable { . . . }
:
Posted by 라면스프