답변:
Joshua Bloch의 Effective Java (Second Edition)에 따르면 finalize()
유용한 두 가지 시나리오 가 있습니다.
하나는 객체의 소유자가 명시적인 종료 방법을 호출하는 것을 잊었을 경우 "안전망"으로 작동하는 것입니다. 종료자가 즉시 호출된다는 보장은 없지만, 클라이언트가 명시 적 종료 메소드를 호출하지 못하는 경우 (종종 드문 경우)에는 리소스를 확보하는 것이 낫습니다. 그러나 종료자는 리소스가 종료되지 않은 것으로 확인되면 경고를 기록해야합니다.
파이널 라이저의 두 번째 합법적 사용은 기본 피어가있는 객체와 관련이 있습니다. 기본 피어는 일반 개체가 기본 메서드를 통해 위임하는 기본 개체입니다. 원시 피어는 일반 오브젝트가 아니므로 가비지 콜렉터는이를 인식하지 못하며 Java 피어가 교정 될 때이를 회수 할 수 없습니다. 파이널 라이저는 기본 피어에 중요한 리소스가 없다고 가정 할 때이 작업을 수행하는 데 적합한 수단입니다. 네이티브 피어가 즉시 종료해야하는 리소스를 보유하는 경우 클래스는 위에서 설명한대로 명시적인 종료 방법을 가져야합니다. 종료 방법은 중요한 리소스를 확보하는 데 필요한 모든 작업을 수행해야합니다.
자세한 내용은 27 페이지 항목 7,를 참조하십시오.
종료자는 기본 리소스 관리에 중요합니다. 예를 들어, 객체가 Java 이외의 API를 사용하여 운영 체제에서 WidgetHandle을 할당해야 할 수 있습니다. 객체가 GC 일 때 해당 WidgetHandle을 해제하지 않으면 WidgetHandles가 유출됩니다.
중요한 것은 "파이널 라이저가 호출되지 않습니다"사례가 단순히 다음과 같이 분류된다는 것입니다.
이 세 가지 경우 모두 (프로그램이 더 이상 실행되고 있지 않다는 이유로 인해) 기본 누수 가 없거나 이미 네이티브가 아닌 누수가 있습니다 (관리 대상 객체를 할당하지 않고 계속 할당하는 경우). GC'd).
"파이널 라이저가 호출되지 않음"경고는 실제로 프로그램 로직에 파이널 라이저를 사용하지 않는 것에 관한 것입니다. 예를 들어, 생성하는 동안 파일의 카운터를 증가시키고 종료 자에서이를 줄임으로써 프로그램의 모든 인스턴스에 존재하는 오브젝트 수를 추적하고 싶지 않습니다. 이 파일 카운터는 0으로 돌아 가지 않을 것입니다. 이것은 실제로 프로그램을 정상적으로 종료하는 데 의존하지 않아야하는 (일반적인 정전 등)보다 일반적인 원칙의 특별한 경우입니다.
그러나 네이티브 리소스를 관리하기 위해 종료자가 실행되지 않는 경우는 실행되지 않는 경우에 신경 쓰지 않는 경우에 해당합니다.
close()
수없는 상태가되기 전에 호출 되지 않음) 종료자가 폴백이라고 말하는 것이 더 정확할 것입니다.
이 방법의 목적은 다음과 같이 API 설명서에 설명되어 있습니다.
Java 가상 머신이 다른 객체의 종료에 의해 취해진 액션의 결과를 제외하고, 아직 죽지 않은 임의의 스레드에 의해이 객체에 액세스 할 수있는 수단이 더 이상 없다고 판단한 경우에 불려갑니다. 또는 완성 될 준비가 된 수업 ...
일반적인 목적은 개체를 취소 할 수 없게 폐기하기 전에 정리 작업
finalize
을 수행하는 것입니다 . 예를 들어, 입출력 연결을 나타내는 객체의 finalize 메소드는 객체가 영구적으로 삭제되기 전에 명시적인 I / O 트랜잭션을 수행하여 연결을 끊을 수 있습니다.
언어 디자이너가 응용 프로그램 프로그래머가 제어 할 수없는 방식 ( "우리는 절대 신뢰할 수 없음") 을 "개체를 취소 할 수 없다"( 가비지 수집 )로 선택한 이유에 추가로 관심 이있는 경우 관련 질문 에 대한 답변 으로 설명되었습니다 . 질문 :
자동 가비지 콜렉션 ... C 및 C ++ 프로그래머에게있어 발생하는 프로그래밍 오류의 전체 클래스를 제거합니다. 시스템에서 많은 오류를 신속하게 발견하고 프로덕션 코드가 배송 될 때까지 주요 문제가 휴면되지 않을 것이라는 확신을 가지고 Java 코드를 개발할 수 있습니다.
위의 인용문 은 Java 디자인 목표에 대한 공식 문서 에서 가져온 것입니다 . 즉, Java 언어 디자이너가 왜 이런 방식으로 결정했는지 설명하는 권위있는 참조로 간주 될 수 있습니다.
이 환경 설정에 대한 더 자세한 언어 독립적 인 논의에 대해서는 OOSC 섹션 9.6 자동 메모리 관리를 참조하십시오 (실제로이 섹션뿐만 아니라 9 장 전체에 관심이 있다면 읽을 가치가 있습니다). 이 섹션은 분명한 진술로 열립니다 :
좋은 OO 환경은 자동 메모리 관리 메커니즘을 제공하여 도달 할 수없는 객체를 감지하고 회수하여 응용 프로그램 개발자가 자신의 업무 (응용 프로그램 개발)에 집중할 수 있도록합니다.
위의 논의는 그러한 시설을 이용할 수있는 것이 얼마나 중요한지를 보여주기에 충분해야합니다. Michael Schweitzer와 Lambert Strether의 말에 따르면 :
자동 메모리 관리 기능이없는 객체 지향 프로그램은 안전 밸브가없는 압력솥과 거의 동일합니다. 조만간 폭발 할 것입니다!
주의 사항 : 나는 구식 일지 모르지만 이것은 몇 년 전의 나의 이해입니다.
일부 JVM에서는 프로그램이 종료되기 전에 완전한 GC 및 종료를 요청할 수 있지만 일반적으로 종료자가 언제 실행되는지 또는 전혀 실행되지는 않습니다. 종료하고 기본 작동 모드가 아님).
그리고 일부 GC는 벤치 마크에서 더 나은 성능을 발휘할 수 있도록 파이널 라이저가있는 GC 객체를 명시 적으로 지연 시키거나 피하는 것으로 알려져 있습니다.
불행히도 이러한 동작은 종료자가 권장 된 원래의 이유와 충돌하며 대신 명시 적으로 종료 된 종료 방법을 사용하도록 권장했습니다.
폐기하기 전에 실제로 청소해야하는 객체가 있고 사용자가 실제로이를 신뢰할 수없는 경우에도 파이널 라이저를 고려해 볼 가치가 있습니다. 그러나 일반적으로 초기 예제 중 일부에서했던 것처럼 현대 Java 코드에서 자주 보지 못하는 좋은 이유가 있습니다.
구글 자바 스타일 가이드는 주제에 몇 가지 현명한 조언이 있습니다 :
재정의하는 것은 매우 드 rare니다
Object.finalize
.팁 :하지 마십시오. 절대적으로 필요한 경우, 먼저 효과적인 Java Item 7, "Avoid Finalizers"를 읽고 이해 한 다음 이해하지 마십시오.
PhantomReference
하고 ReferenceQueue
대신.
PhantomReference
더 나은 솔루션 이라고 생각 합니다. 파이널 라이저는 Java 초기부터 남은 사마귀이며 like Object.clone()
및 raw 유형은 가장 잊혀진 언어의 일부입니다.
Java 언어 사양 (자바 SE 7) 상태 :
Finalizer는 자동 스토리지 관리자가 자동으로 해제 할 수없는 리소스를 확보 할 수있는 기회를 제공합니다. 이러한 상황에서 객체가 사용하는 메모리를 단순히 회수한다고해서 보유한 리소스가 회수되는 것은 아닙니다.