[Item8] finalizer와 cleaner 사용을 피하라

Sera Lee·2022년 2월 21일
0

EffactiveJava

목록 보기
7/9
post-thumbnail

Finalizer(deprecated at java9)

  • 종료자라고 한다.
  • JVM이 특정 인스턴스를 가비지 수집해야 한다고 판단되면 filnalize가 호출된다.

사용을 지양해야 하는 이유

  • java9 에서부터는 deprecated 됐다. → 사용하지 말라는 말이다.
  • GC 가 finalize 를 호출하는 시간은 정확히 알 수 없다. GC가 언제 수행되는지 알 수 없으니까,,,
  • gc 수집이 수행되지 전에 리소스가 부족 할 수 있으며, 이로 인해 시스템 충돌이 발생할 수 있다.
  • GC 으 효율을 떨어뜨린다.
  • 보안문제를 일으킬 수 잇다.

언제 써야 할까

  • 이중장치
    • 자원의 소유자가 close 를 호출하지 않은 것에 대비하 안전망
    • finalize를 제공하는 클래스
      • FileInputStream
      • FileOutputStream
      • ThreadPoolExecutor
  • 네이티브 피어와 연결된 객체
    • Java가 아닌 다른 플랫폼 언어로 프로그래밍 된 객체
      • ex) jni
    • GC 에서 삭제가 불가능하다
      • finalize 나 cleaner에 맡길 수 있다.
        • 성능저하를 감당할 수 없거나, 심각한 자원을 가지지 않는 경우에만 해당한다.
      • close 를 사용하자

cleaner 사용예제(WIP)

  • 안전망으로 쓰이면 좋다.
    • 채팅에서 Connection 에서 사용하면 좋음

💎 정상적으로 자원을 반납하는 방법

AutoClosable

  • 파일이나 스레드 등 종료해야할 자원의 클래스에 AutoCloseable 을 구현해주고,
  • 클라이언트에서 인스턴스를 다 쓰면 close 메서드를 호출한다.
public class TestResource implements AutoCloseable {
	@Override
	public void close() throws RuntimeException {
		System.out.println("close");
	}

	public void hello() {
		System.out.println("hello");
	}
}

-------------------------------------------------------------
public class TestRunner {
	public static void main(String[] args) {
		try {
			TestResource resource = new TestResource();
			resource.hello(); // 리소스 사용
		} finally {
			resource.close(); // 리소스를 사용하는 쪽에서 쓴 다음 반드시 정리. close() 호출
		}
	}
}

❗결론

finalize, cleaner 를 이용하여, 자원을 종료하는 방법은 옳은 방법이 아니다. Autoclosable 을 구현해 주고, try-with-resource 사용을 지향하자. try-with-resource 는 안전하게 리소스를 종료해주는 것 이외에도 가독성이 좋은 코드를 작성할 수 있다는 장점이 있다.

0개의 댓글