ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 아이템8. finalizer와 cleaner 사용을 피하라
    책/이펙티브자바 2021. 6. 26. 18:33

    자바에서는 두 가지 객체 소멸 자를 제공한다.

    finalizer

    • 오동작, 낮은 성능
    • 예측할 수 없고 위험하여 일반적으로 불필요하다.
    • 자신을 수행할 스레드를 제어할 수 없다.
    • finalizer 공격에 노출되어 심각한 보안문제를 일으킬 수 있다.
      • 생성자나 직렬화 과정에서 예외가 발생하면, 악의적으로 하위 클래스의 finalizer가 수행될 수도 있다.
        • GC가 수집하지 못하게 막을 수 있다.
    • 위와 같은 이유로 Java9 에서 deprecated 되었고 새로운 대안으로 cleaner를 소개한다.

    cleaner

    • finalizer 보다는 덜 위험하다.
    • 하지만 여전히 예측할 수 없고, 느리고, 일반적으로 불필요하다.
    • 자신을 수행할 스레드를 제어할 수 있다.

    공통사항

    • 즉시 수행된다는 보장이 없다.
    • 실행되기까지 얼마나 걸릴지 알 수 가없다.
    • 제때 실행되어야 하는 작업은 절대 할 수 없다.
    • 심각한 성능문제를 동반한다.
    • 얼마나 신속히 수행할지는 전적으로 GC 알고리즘에 달렸다.

    그러면 finalizer 와 cleaner는 어디에 쓰이는가 ?

    • 자원의 소유자가 close 메서드를 호출하지 않는 것에 대비한 안전망 역할
      • 즉시 수행한다는 보장은 없지만 아예 안하는 것보다는 낫다.
      • 라이브러리의 일부 클래스는 안전망 역할의 finalizer를 제공한다.
        • ex) FileInputStream, FileOutputStream, ThreadPoolExcecutor
    • 네이티브 피어 (native peer)와 연결된 객체
      • 네이티브 피어 ?
        • 일반 자바 객체가 네이티브 메서드를 통해서 기능을 위임한 네이티브 객체
      • GC 가 자바객체가 아니니 존재를 알지 못한다.
        • 회수하지 못함
        • finalizer나 cleaner 가 나서서 처리하기에 적당한 작업
      • 단, 성능 저하를 감당할 수 있고 네이티브 피어가 심각한 자원을 가지고 있지 않을 때에만 해당된다.

    대안

    그러면 파일이나 스레드 등 종료해야 할 자원을 담고 있는 객체의 클래스에서 어떻게 해야할까 ?

    • AutoCloseable을 구현하고 클라이언트에서 인스턴스를 다 쓰고 나면 close 메소드를 호출하면 된다.
    • (일반적으로 예외가 발생해도 제대로 종료되도록 try-with-resource 사용이 권장된다.)

    결론

    cleaner는 안전망 역할이나 중요하지 않은 네이티브 자원 회수용으로만 사용한다.

    물론 이런경우라도 불확실성과 성능 저하에 주의해야 한다.

킹수빈닷컴