개발 공부 기록하기/01. JAVA & Kotlin

짧은 코멘트와 함께하는 이펙티브 자바) #8 finalizer와 cleaner사용을 피하라

lannstark 2020. 9. 25. 11:19

짧은 코멘트

  1. 실제로 사용해본적이 없다.
  2. ThreadPoolExecutor가 finalizer 역할을 제공한다고 되어 있지만 JDK 버전에 따라 다른 모습을 보여준다. (모든 버전을 확인해본 것은 아니지만, 9버전부터 아무것도 하지 않게 변경된 것 같다.
// Override without "throws Throwable" for compatibility with subclasses
// whose finalize method invokes super.finalize() (as is recommended).
// Before JDK 11, finalize() had a non-empty method body.

/**
 * @implNote Previous versions of this class had a finalize method
 * that shut down this executor, but in this version, finalize
 * does nothing.
 */
@Deprecated(since="9")
protected void finalize() {}

finalizer와 cleaner 사용을 피하라

JAVA의 소멸자인 finalizer와 cleaner는 예측할 수 없고, 상황에 따라 위험할 수 있어 일반적으로 불필요 하다. 제때 실행되어야 하는 작업도 수행할 수 없으며 심각한 성능 문제도 동반하고, finalizer의 경우 finalizer 공격에 노출되어 보안 문제를 일으킬 수도 있다

finalizer와 cleaner가 필요할 여지가 조금은 있는 경우는 두 가지 이다

 

1. 자원의 소유자가 close 메소드를 호출하지 않는 것에 대비한 안전망 역할

FileInputStream, FileOutputStream, ThreadPoolExecutor 등은 안전망 역할의 finalizer를 제공한다

 

2. Native Peer와 연결된 객체

Native Peer란 일반 자바 객체가 Native 메소드를 통해 기능을 위임한 네이티브 객체를 말한다. 이 네이티브 객체는 JAVA 객체가 아니니 가비지 컬렉터가 그 존재를 알지 못한다. 이럴 때 cleaner나 finalizer가 나서서 native 객체를 처리할 수 있다 물론, 성능 저하를 감수할 수 있고 네이티브 피어가 심각한 자원을 가지고 있지 않을 때에만 해당된다. 네이티브 피어가 사용하는 자원을 즉시 회수해야 한다면 앞서 설명한 close 메소드를 사용해야 한다