최종 평가 견적
이 클래스는 패키지 유형으로, 공개 부분이 아니며 참조에서 상속되므로 특정 참조 유형이라는 것을 의미합니다. 따라서, 랩핑 된 각 물체가 재활용되기 전에 지정된 referqyebcequeue에 배치됩니다.
이 참조 객체는 완료 메소드가있는 클래스에 특별히 사용됩니다. 해당 방법을 가진 모든 객체는 최종 반등 객체로 캡슐화 될 것임을 이해할 수 있습니다.
최종 메소드는 객체에 의해 정의되므로 기본 구현이 비어 있습니다. 그런 다음이 메소드를 다시 작성하면 방법 본문이 분명히 비어 있지 않습니다. 이 차이는 이것을 통해 이루어질 수 있습니다. Finalize 메소드가 비어 있지 않은 클래스를 구현하는 한, 생성 된 객체는 Final -Refernece에 등록되어야합니다.
이 단계는 NewInstance 동안 객체 기본 생성자 메소드를 호출하여 그에 따라 등록 할 수 있습니다.
Finalizer#레지스터 방법
이 메소드가 주로 호출되면 해당 파이널 라이저 객체가 생성되고 Finalizer 객체는 FinalReference에서 상속됩니다. 이 방법은 다음과 같이 선언됩니다.
/ * vm */static void Register (Object Finalizee) {New Finalizer (Finalizee);} 위의 주석에서 볼 수 있듯이이 방법은 특정 기간에 JVM에 의해 호출됩니다.
그런 다음 아래와 같이 Finalizer의 생성자로 전환하십시오.
Private Finalizer (Object Finalizee) {Super (Finalizee, Queue); 추가하다();} 해당 참조 객체가 큐를 통해 다시 호출된다는 것을 알 수 있습니다. ADD의 기능은 메소드를 아직 마무리하지 않은 모든 객체를 저장하고 최종 System.shutdown 에서 호출하는 것입니다. Runtime#runFinalizersOnExit 통해 설정하십시오.
참조 큐
이 참조 대기열은 해당 참조 객체의 내부 객체가 재활용되기 전에이 대기열에 배치됩니다 (자세한 설명은 참조에 관한 다른 기사에서 설명됩니다.)이 큐에서 해당 객체 만 얻어야하기 때문에이 객체는 확실히 재활용 될 준비가되어 있습니다.
그런 다음 재활용하기 전에 해당 마무리 방법을 호출하십시오.
FinalizerThread 스레드
이 스레드는 큐에서 데이터를 계속 얻은 다음 해당 최종 메소드를 호출합니다. 해당 코드는 다음과 같습니다.
for (;;) {try {finalizer f = (finalizer) queue.remove (); F.Runfinalizer (JLA); } catch (InterruptedException x) {// 무시하고 계속}}}해당 Runfinalizer는 다음과 같습니다.
동기화 된 (this) {if (hasbeenfinalized ()) return; remove ();} try {객체 finalize = this.get (); if (finalizee! = null &&! / * 보수적 인 gc */ finalizee = null로 오 탐지 가능성을 줄이기 위해이 변수를 포함하는 투명 스택 슬롯; }} catch (Throwable x) {} super.clear ();위의 논리에서 먼저 전화를 걸고 결승에서 제거하십시오. 이 방법은 각 객체의 마무리가 최대 한 번만 호출되도록하는 것입니다. 즉, 현재 호출이 완료됩니다. 그것은 해당 상태, 즉 Hasbeenfinalized Returns True에 기록 될 것입니다 (사실, 다음 포인터를 그 자체로 가리키는 것을 의미합니다. 즉, 마무리되지 않았으며 다시 Finalize를 호출 할 필요가 없습니다).
다음은 해당 마무리 방법을 호출하는 것입니다. 위의 jla.invokeFinalize 실제로 해당 객체의 최종 메소드를 호출하는 것입니다. 이 과정에서 원래 객체는 Get을 통해 먼저 얻습니다. 전체 JVM 프로세스에서, 최종화 회의를 위해 재활용하기 전에 참조는 NULL로 설정되지 않습니다. 여기서 해당 참조 객체를 항상 얻을 수 있기 때문입니다.
처리 후, 해당 명확성이 마침내 호출되어 해당 참조를 지우십시오. 이는 다른 객체가 참조 할 다른 객체가없는 최종 참조의 효과를 달성합니다.
위의 처리에서는 최종 호출 시간에 제한이 없습니다. 따라서 객체의 마무리가 천천히 호출되면 전체 재활용 체인의 실행에 영향을 미치고 해당 OOM 예외가 생성됩니다. 따라서 특별한 경우가 아니라면 마무리를 다시 쓰지 마십시오. 해당 시나리오를 처리하는 다른 방법이 있어야합니다. 예를 들어, Guava의 FinalizableReference.
Finalizer가 스레드를 시작합니다
위의 스레드에서는 해당 프로세스 시작 중에 시작됩니다. 객체가 register(object) 호출하여 Finalizer 클래스의 초기화를 트리거한다는 것을 이해할 수 있습니다. 그런 다음 정적 초기화 블록에서 해당 재활용 스레드가 시작됩니다. 해당 초기화 코드는 다음과 같습니다.
static {ThreadGroup tg = thread.currentThread (). getThreadGroup (); for (ordregroup tgn = tg; tgn! = null; tg = tg, tgn = tg.getParent ()); 스레드 Finalizer = New FinalizerThread (TG); finalizer.setpriority (thread.max_priority -2); finalizer.setdaemon (true); finalizer.start ();}위의 정적은 정적 초기화 블록입니다. 즉, 클래스 최종화기가 사용되는 한 해당 호출이 트리거됩니다. 여기에 사용 된 스레드 그룹은 시스템 스레드 그룹이며 우선 순위는 여전히 비교적 높으며 백그라운드 스레드로 구성됩니다.
Jstack을 사용하여 스레드를 인쇄 할 때 그림 아래에 표시된 스레드가 여기에서 시작됩니다. 아래 그림과 같이
요약
전체 최종화기는 JVM 및 해당 Java 클래스의 최종 추천을 통해 함께 작동합니다. JVM에 의해 모두 구현 된 것은 아니므로 너무 근본적이 아니라 해당 의미를 구현하는 것으로 간주 될 수 있습니다. 모든 것은 정상적인 Java에 의해 이루어지며 JVM에 의해 협력합니다. 전체 프로세스를 이해하는 것은 또한 Java 자체의 실행 메커니즘을 이해하는 것입니다.