ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Item 8. finalizer와 cleaner 사용을 피하라
    백수의 개발/이펙티브 자바 2019. 8. 7. 16:34

    finalizer와 cleaner를 피해야하는 이유

    자바는 finalizer와 cleaner 두 가지 객체 소멸자를 제공한다.

    finalizer는 예측할 수 없고, 상황에 따라 위험할 수 있어 일반적으로 불필요하다.

    cleaner는 finalizer보다는 덜 위험하지만, 여전히 예측할 수 없고, 느리고, 일반적으로는 불필요하다.

     

    1. 실행을 보장할 수 없다.

    위 두 가지 객체 소멸자로는 즉시 수행된다는 보장이 없다.

    객체에 접근할 수 없게 된 후 finalizer나 cleaner가 실행되기까지 얼마나 걸릴지 알 수 없다.

    즉, 이 두 가지 객체 소멸자로는 제때 실행되어야 하는 작업은 절대 할 수 없다.

     

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

     

    2. 성능이 좋지 않다.

    finalizer는 가비지 컬렉터의 효율을 떨어뜨린다. cleaner 또한 클래스의 모든 인스턴스를 수거하는 형태로 사용하면 성능은 finalizer와 비슷하다.

    AutoCloseable와 finalizer를 통해 카비지 컬렉터가 수거하는 시간을 비교했을 때 finalizer가 약 50배 느린 것을 확인 할 수 있다.

     

    3. finalizer는 보안에 취약하다.

    finalizer는 생성자나 직렬화 과정에서 예외가 발생하면, 이 생성되다 만 객체에서 악의적인 하위 클래스의 finalizer가 수행 될 수 있게 된다.

    또한, 정적 필드에 자신의 참조를 할당하여 가비지 컬렉터가 수집하지 못하게 막을 수 도 있다.

     

    이러한 보안 해결책은 다음과 같다. 

    1.객체 생성을 막기 위해 생성자에서 예외 던지기

    2. final 클래스로 만들어 하위 클래스를 만들 수 없도록 하기

    3. 아무 일도 하지 않는 finalize메서드 생성 후 final로 선언

     

     

    finalizer와 cleaner를 사용하는 경우는?

    finalizer와 cleaner가 즉시 호출되리라는 보장은 없지만, 자원의 소유자가 cloase메서드를 호출하지 않아 자원 회수가 아예 일어나지 않는 것 보다 클라이언트가 하지 않은 자원 회수를 늦게라도 해주기 위해 사용한다.

     

    네이티브 피어는 자바 객체가 아니라 가비지 컬렉터는 그 존재를 알지 못한다. 그 결과 자바 피어를 회수 할 때 네이티브 객체까지 회수하지 못한다. 따라서 finalizer나 cleaner로 처리하기 적절한 작업이다. 단, 성능 저하를 감당한 수 있고, 네이티브 피어가 심각한 자원을 가지고 있지 않을 때에만 해당된다.

    성능 저하를 감당할 수 없거나 네이티브 피어가 사용하는 자원을 즉시 회수해야 한다면 close메서드를 사용해야 한다.

     

    *네이티브 피어(native peer) : 일반 자바 객체가 네이티브 메서드를 통해 기능을 위임한 네이티브 객체

     

    마무리

    finalizer와 cleaner는 안전망 역할이나 중요하지 않은 네이티브 자원 회수용으로만 사용하자. 물론 이런 경우라도 불확실성과 성능 저하에 주의해야 한다.

    댓글

Designed by Tistory.