finalize() 메소드란?

JVM이 메모리 누수를 방지하기위해 실행하는 GC가 수행될 때 더 이상 사용하지 않는 자원에 대한 정리작업을 할 때 호출하는 메소드. 이러한 종료자의 치명적인 단점이 있다. 

바로 즉시 실행되리라는 보장이 전혀 없다는 것.

 따라서 긴급한 작업을 종료자 안에서 처리하면 안된다!!. 예를 들어 파일을 닫도록 하는 작업, 자원을 반납하는 작업 등.. System.gc , System.runFinalization 같은 메서드는 종료자가 실행 될 가능성을 높여주긴 하지만 여전히 보장하진 않는다. ( 종료자는 자바명세서에도  즉시 실행되어야 한다는 구문도 없지만, 반드시 실행되어야 한다는 구문도 없다. ㅎㄷㄷ...)

종료자의 문제점은 이 뿐만이 아니다.

 일반적으로는 uncaught 예외가 던져지면 스레드는 종료되고 StackTrace가 표시되지만, 종료자 안에서는 아니다. 경고문 조차 발생하지 않는다..

또한, 종료자를 사용하면 프로그램 성능이 심각하게 떨어진다. (객체 메모리 해제 등의 이유로..)

그럼 자원의 반환 / 삭제는 어떻게?

명시적인 종료 메소드를 하나 정의하고, 객체 내에서 유효하지 않은 객체임을 표시하는 private 필드를 하나 두고, 모든 메서드 맨 앞에 해당 필드를 검사하는 코드를 두어서 유효하지 않은 객체면 예외를 던지도록 한다. 이런 명시적인 종료 메서드는 보통 객체 종료를 보장하기 위해 try/catch과 함께 쓰인다.

정말 정말 종료자는 쓸 곳이 없는 녀석인가..!? ( 이것도 1번 빼고 딱히..?)

1. 명시적 종료 메서드 호출을 잊을 경우에 대비하는 안전망의 역할. 종료자는 그런 자원을 발견하게 될 경우 반드시 경고 메세지를 로그로 남겨서 코드가 잘못되어있음을 알려야 한다.

2.네이티브 피어와 연결된 객체를 다룰 때 사용될 수도 있다. 

3.하위 클래스에서 상위 클래스 종료자를 재정의 하면서 상위 클래스 종료자 호출을 잊으면, 상위 클래스 종료자는 절대 호출되지 않는다. 따라서 아래와 같이 처리할 수 있다.


위와 같이 상위 클래스의 종료자 호출을 하지 않았을 때의 문제를 방지하는 한 가지 방법은, 종료되어야 하는 모든 객체마다 여벌의 객체를 하나 더 만드는 것이다.



위와 같은 익명클래스를 종료보호자라고 부른다.


요약

자원 반환에 대한 최종적 안전장치를 구현하거나, 그다지 중요하지 않은 네이티브 자원을 종료시키는 것이 아니라면 종료자는 사용하지 말자


+ Recent posts