이 글에서는 주로 Java에서 finalize 메소드 사용 금지 사항을 소개합니다. 필요하신 분들은 참고하시면 됩니다
finalize 메소드란 무엇인가요?
finalize() 메소드는 Java.lang.Object에 정의되어 있습니다. 이는 모든 클래스가 이 메서드를 오버로드할 수 있음을 의미합니다. Java 가비지 수집기는 new를 통해 할당된 메모리만 해제할 수 있으므로 개체가 new를 통해 얻은 메모리가 아닌 경우 가비지 수집기는 개체의 메모리를 해제하는 방법을 모릅니다.
이러한 상황에 대처하기 위해 Java에서는 클래스 내의 java.lang.Object 클래스에 finalize() 메서드를 오버로드하는 것을 허용합니다.
작동 방식: 가비지 수집기가 객체가 차지하는 저장 공간을 해제할 준비가 되면 해당 finalize() 메서드가 먼저 호출되고 객체가 차지하는 메모리는 다음 가비지 수집 작업이 수행될 때까지 실제로 회수되지 않습니다. 발생합니다.
finalize 함수의 호출 메커니즘
Java Virtual Machine 사양은 가비지 수집을 수행해야 하는지 여부와 수행 방법을 엄격하게 규정하지 않습니다. 따라서 여기에 언급된 호출 메커니즘은 모든 JVM에 적합하다고 보장되지 않습니다.
언제 부르나요?
Finalize는 언제 호출되나요? 일반적으로 JVM이 가비지 수집을 시작할 때까지 호출되지 않을 수 있습니다. JVM이 가비지 수집을 수행하는 시점은 매우 불확실하며 다양한 런타임 환경 요인에 따라 달라집니다. 나중에 언급할 몇 가지 단점을 초래하는 것은 바로 finalize 함수 호출 시간의 불확실성 때문입니다.
누가 전화할까요?
일반적인 JVM은 GC의 가비지 수집 스레드를 통해 마무리 기능을 호출합니다. 가비지 수집 스레드는 매우 중요하므로(결국 JVM의 필수 부분이기도 함) finalize 함수에서 발생하는 예외가 가비지 수집 스레드의 작업에 영향을 미치는 것을 방지하기 위해 가비지 수집 스레드는 다음 작업을 수행합니다. 각 finalize 함수를 호출할 때 catch를 시도하세요. 만약 예외가 발생하면 바로 폐기하고 다음 유효하지 않은 객체의 finalize 함수를 처리합니다.
finalize() 사용이 금지되는 이유
1. 호출 시간이 불확실합니다---자원 낭비의 위험이 있습니다
호출 메커니즘은 이전에 도입되었습니다. 학생들은 "finalize를 호출하는 시점이 매우 불확실하다"는 사실을 인식해야 합니다. 따라서 finalize()에서 일부 희소 리소스를 해제하면 희소 리소스가 해제되기까지 아주 오랜 시간 동안 기다려야 할 수 있습니다. 이것은 자원 낭비입니다! 또한 특정 클래스 개체(예: 일부 JDBC 클래스)가 전달하는 리소스는 자체적으로 많은 메모리를 소비할 수 있으며 이러한 리소스의 지연된 릴리스는 큰 성능 문제를 일으킬 수 있습니다.
2. 호출되지 않을 수 있음---리소스 유출 위험이 있습니다
많은 학생들이 finalize()가 항상 호출될 것이라고 생각하지만 그렇지 않습니다. 어떤 경우에는 finalize()가 전혀 호출되지 않습니다. 예를 들어 JVM이 종료되면 메모리에 있는 해당 객체의 종료 기능이 호출되지 않을 수 있습니다.
일부 학생들은 JVM이 종료되기 전에 모든 종료가 호출되도록 "runFinalizersOnExit"을 생각하고 있는 것으로 추정됩니다. JDK 1.2부터 이 방법이 폐기된 것은 안타깝고 유감스러운 일입니다. 이 방법을 포기하지 않더라도 여전히 스레드 안전에 큰 위험이 있습니다!
위에서 볼 수 있듯이 일단 finalize()를 사용하여 리소스를 해제하는 것은 매우 나쁜 일입니다(리소스 유출의 위험이 있습니다)! 리소스 누수로 인한 성능 문제는 더 심각하므로 과소평가해서는 안 되는 경우가 많습니다.
3. finalize 함수가 호출되면 객체가 부활할 수 있습니다.
원래 객체가 만료된 경우(참조 없음)에만 가비지 수집기가 객체의 finalize 함수를 호출합니다. 그러나 변태 프로그래머를 만나 객체 자체 참조(즉, this)를 finalize() 함수 내부 어딘가에 다시 저장하면 이는 자신을 부활시키는 것과 같습니다(객체에 새 참조가 있고 더 이상 유효하지 않은 위치에 있지 않기 때문입니다). 상태). 이런 이상한 일이 발생하는 것을 방지하기 위해 가비지 수집기는 finalize()를 호출할 때마다 개체가 여전히 유효하지 않은 상태인지 여부만 확인할 수 있습니다. 이는 사실상 JVM의 오버헤드를 증가시킵니다. 그냥 아무렇지도 않게 언급하세요. JDK 문서에 규정된 대로 JVM은 각 클래스 객체 인스턴스에 대해 최대 한 번만 finalize()를 호출합니다. 따라서 가짜 시체의 경우 실제로 죽을 때 finalize()가 호출되지 않습니다. 이거 이상해 보이지 않나요?
4. 예외를 직접 잡아야 한다는 점을 기억하세요.
finalize() 호출 메커니즘을 소개할 때 방금 언급한 것처럼, finalize 함수 외부에서 예외가 발생하면 가비지 수집 스레드에 의해 포착되어 삭제됩니다. 즉, 예외가 무시됩니다(무시된 예외의 위험성은 "여기"에 언급되어 있습니다). 이런 일을 방지하려면 finalize()에서 예외가 발생할 수 있는 모든 코드에 대해 try catch 문을 작성하고 직접 잡아야 합니다.
5. 스레드 안전에 주의하세요
finalize()는 가비지 수집 스레드에 의해 호출되므로 자신의 코드와 동일한 스레드가 아닙니다. 심지어 다른 객체의 finalize()도 다른 가비지 수집 스레드에 의해 호출될 수 있습니다(예: "병렬 수집기"를 사용하는 경우) . 따라서 finalize()에서 특정 데이터에 접근할 때는 항상 스레드 안전성 문제에 주의해야 합니다.
요약
위 내용은 Java에서 finalize 사용을 금지하는 방법 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!