자바의 2가지 객체 소멸자

finalizer

객체가 GC에 의해 제거될 때 가장 마지막으로 수행되는 작업

Cleaner

사용 지양을 권하는 이유

  1. 예측 불가능

    1. finalizer와 cleaner는 즉시 수행된다는 보장이 없다.

      → 실행되기까지 얼마나 걸리는 지 알 수 없기 때문

    2. 전적으로 GC 알고리즘에 달렸다.

    3. 클래스에 finalizer를 달아두면 그 인스턴스의 자원 회수가 제멋대로 지연될 수 있다.

      • OOM(OutOfMemoryError)를 내며 죽는 애플리케이션을 분석해보니, 죽는 시점에 그래픽스 객체 수천 개가 finalizer 대기열에서 회수되기만을 기다리고 있었다.
      • finalizer 스레드는 다른 애플리케이션 스레드보다 우선순위가 낮아서 실행될 기회를 제대로 얻지 못한다. → 해결법은 사용하지 않는 방법 뿐!
      • cleaner는 자신을 수행할 스레드를 제어할 수 있다. → 백그라운드에서 수행되며 GC 통제하에 있어 즉각 수행을 보장하기 어려움!
  2. 수행 여부를 보장하지 않음

    1. 상태를 영구적으로 수정하는 작업에서는 절대 finalizer나 cleaner에 의존하면 안된다.

    2. System.gcSystem.runFinalization 에 현혹되지 말자

      (실행될 가능성을 높여줄 수 있으나, 보장하진 않는다.)

    3. 동작하더라도, 실행 중 발생한 예외는 무시되며 처리할 작업이 남았더라도 그 순간 종료된다. 자칫 마무리가 덜 된 상태로 남을 수 있다.

      • 훼손된 객체를 다른 스레드가 사용하더라도, finalilzer는 어떠한 경고도 출력하지 않는다.
      • 훼손된 객체를 다른 스레드가 사용한다면, cleaner는 사용하는 라이브러리는 자신의 스레드를 통제하기 때문에 문제는 발생하지 않는다.