programing

Java에서 finalize() 메서드는 언제 호출됩니까?

kingscode 2022. 10. 1. 21:11
반응형

Java에서 finalize() 메서드는 언제 호출됩니까?

메서드가 언제 호출되는지 알아야 합니다.JVM. 테스트 클래스를 만들었습니다.이 클래스는, 다음의 경우에 파일에 씁니다.finalize()메서드는 덮어쓰기로 호출됩니다.실행되지 않습니다.왜 그것이 실행되지 않는지 누가 나에게 이유를 말해줄 수 있나요?

finalize메서드는 개체가 가비지를 수집하려고 할 때 호출됩니다.그것은 가비지 수집 대상이 된 후 언제든지 가능합니다.

되지 않을 에 주의해 주십시오( 쓰레기는 수집되지 않습니다).finalize는 호출되지 않습니다).이 문제는 개체가 gc에 대한 자격이 전혀 없는 경우(JVM의 전체 수명 동안 도달할 수 있기 때문에) 또는 개체가 자격이 부여된 시점부터 JVM 실행 중지 시점(단순 테스트 프로그램에서 자주 발생) 사이에 실제로 가비지 컬렉션이 실행되지 않는 경우에 발생할 수 있습니다.

에 JVM을 .finalize아직 호출되지 않은 오브젝트에 대해서도 마찬가지입니다(그 방법의 보증도 그다지 강하지 않습니다).

「 」에 finalize어플리케이션의 올바른 동작을 위해서라면, 당신은 뭔가 잘못된 것을 하고 있는 것입니다. finalize는 (일반적으로 Java 이외의) 자원의 청소에만 사용해야 합니다.는 JVM이 이를 보증하지 않기 때문입니다.finalize는 어떤 오브젝트에서도 호출됩니다.

것이 finalize()소소등등등하

Javadoc에 따르면 다음과 같습니다.

가비지 컬렉션에서 개체에 대한 참조가 더 이상 없는 것으로 확인되면 개체의 가비지 컬렉터에 의해 호출됩니다.

요아힘이 지적했듯이 오브젝트가 항상 접근 가능하다면 프로그램의 수명 동안 이러한 일은 결코 일어나지 않을 수 있습니다.

또한 가비지 콜렉터는 특정 시간에 실행이 보장되지 않습니다.일반적으로 제가 말하고자 하는 것은finalize()특별한 용도가 없는 한 일반적으로는 사용하지 않는 것이 좋습니다.

protected void finalize() throws Throwable {}
  • 는 ""를 합니다.finalize() javacontraction.contractions.contraction ada ★★★
  • 오브젝트에 대한 참조가 더 이상 존재하지 않는다고 판단되면 가비지 컬렉터에 의해 메서드가 호출됩니다.
  • Object finalize 메서드는 액션을 수행하지 않지만 모든 클래스에 의해 재정의될 수 있습니다.
  • 일반적으로 파일을 닫는 것과 같이 Java 이외의 리소스를 정리하는 것이 우선됩니다.
  • finalize() try-display-display를 호출하는 .super.finalize() 클래스 「」가 하고 있는 위한 안전 대책입니다.

    protected void finalize() throws Throwable {
         try {
             close();        // close open files
         } finally {
             super.finalize();
         }
     }
    
  • 에 의해 finalize() 수집 중 되지만 그 됩니다.

  • finalize()는 어떤 에서도 한 번 .

인용처: http://www.janeg.ca/scjp/gc/finalize.html

다음 기사도 확인하실 수 있습니다.

finalize()가 아니기 는 안 됩니다.에는 Java가 .finalize응용 프로그램 라이브 타임 중에 메서드가 호출됩니다.

것은 당당이inationinationinationinationinationinationinationinationinationinationinationinationinationinationinationination what what what what what what what what what what what 의 조합입니다.finally 방법 " )을 참조해 주세요.

MyClass myObj;

try {
    myObj = new MyClass();

    // ...
} finally {
    if (null != myObj) {
        myObj.cleanup();
    }
}

'어울리다'가 '어울리다'로군요.MyClass()이치노

효과적인 Java, 제2판 27페이지를 참조하십시오.항목 7: 피니셔 피니셔

파이널라이저는 예측할 수 없고 위험하며 일반적으로 불필요합니다.파이널라이저에서는 시간적으로 중요한 작업을 하지 마십시오.중요한 지속 상태를 업데이트하기 위해 최종자에 의존하지 마십시오.

리소스를 종료하려면 대신 try-finally를 사용합니다.

// try-finally block guarantees execution of termination method
Foo foo = new Foo(...);
try {
    // Do what must be done with foo
    ...
} finally {
    foo.terminate(); // Explicit termination method
}

finalize()자바에서 호출되는 메서드

Finalize 메서드는 GC가 오브젝트에 도달할 수 없음을 검출한 후 오브젝트가 사용한 메모리를 실제로 회수하기 전에 호출됩니다.

  • 도달 않는 는, 「」를 참조해 .finalize()절대 호출되지 않을 것이다.

  • GC가 실행됩니다.finalize()이 가치가 했을 때만 됩니다.(GC는 GC실행되기 때문에 판단될 때)

  • GC가 특정 오브젝트에 도달할 수 없다고 판단할 때까지 여러 GC 사이클이 걸릴 수 있습니다.(Java GC는 일반적으로 '세대' 수집기입니다.)

  • GC는 오브젝트가 도달 불능 및 최종 가능함을 검출하면 최종 큐에 배치됩니다.일반적으로 최종화는 일반 GC와 비동기적으로 이루어집니다.

(JVM 사양에서는 오브젝트가 사용하는 공간을 재확보하지 않는 한 JVM은 피니셔를 실행하지 않습니다.이렇게 구현된 JVM은 기능하지 않거나 사용할 수 없지만, 이 동작은 "허용"됩니다.)

결론은 정해진 기간 내에 완료되어야 하는 일을 최종화에 의존하는 것은 현명하지 않다는 것이다.그것들을 전혀 사용하지 않는 것이 "베스트 프랙티스"입니다.에 더 할 수 있는).finalize()★★★★★★ 。

완료를 위한 합법적인 유일한 용도는 애플리케이션 코드에 의해 손실된 개체와 관련된 리소스를 정리하는 것입니다.그 후에도 애초에 오브젝트가 손실되지 않도록 어플리케이션코드를 작성해야 합니다.(예를 들어 Java 7+ try-with-resources를 사용하여 다음 사항을 확인합니다.close()는 항상 라고 불리고 있습니다.라고 불리고 있습니다.


finalize() 메서드를 오버라이드하여 호출하면 파일에 쓰는 테스트 클래스를 만들었습니다.실행되지 않습니다.왜 그것이 실행되지 않는지 누가 나에게 이유를 말해줄 수 있나요?

말하기 어렵지만 몇 가지 가능성이 있습니다.

  • 개체가 아직 연결할 수 있으므로 가비지가 수집되지 않았습니다.
  • 테스트가 완료되기 전에 GC가 실행되지 않으므로 개체가 가비지 수집되지 않습니다.
  • 오브젝트는 GC에 의해 검출되어 GC에 의해 최종화 큐에 배치되지만 최종화는 테스트가 완료될 때까지 완료되지 않습니다.

JVM에finalize() finalize()가 알 수 없음()가호출되었을 때 이 일어나는지 좋은 은 JVM이 finalize() 로 가비지 입니다. 여부를 알 수 없음), finalize()가 호출되었을 때 어떤 일이 일어나는지 관찰하기 위한 보다 좋은 방법은 JVM이 명령어로 가비지 수집을 호출하도록 강제하는 것입니다.System.gc().

구체적으로는 오브젝트가 사용되지 않게 되었을 때 finalize()가 호출됩니다.. 확실히 위해 는 '만들기'를 .null ★★★c가 없기 때문에, 「이러다」를 볼 수 있습니다.c가 콜을 종료합니다.

class Car {

    int maxspeed;

    Car() {
        maxspeed = 70;
    }

    protected void finalize() {

    // Originally finalize method does nothing, but here we override finalize() saying it to print some stmt
    // Calling of finalize is uncertain. Difficult to observe so we force JVM to call it by System.gc(); GarbageCollection

        System.out.println("Called finalize method in class Car...");
    }
}

class Bike {

    int maxspeed;

    Bike() {
        maxspeed = 50;
    }

    protected void finalize() {
        System.out.println("Called finalize method in class Bike...");
    }
}

class Example {

    public static void main(String args[]) {
        Car c = new Car();
        c = null;    // if c weren`t null JVM wouldn't be certain it's cleared or not, null means has no future use or no longer in use hence clears it
        Bike b = new Bike();
        System.gc();    // should clear c, but not b
        for (b.maxspeed = 1; b.maxspeed <= 70; b.maxspeed++) {
            System.out.print("\t" + b.maxspeed);
            if (b.maxspeed > 50) {
                System.out.println("Over Speed. Pls slow down.");
            }
        }
    }
}

산출량

    Called finalize method in class Car...
            1       2       3       4       5       6       7       8       9
    10      11      12      13      14      15      16      17      18      19
    20      21      22      23      24      25      26      27      28      29
    30      31      32      33      34      35      36      37      38      39
    40      41      42      43      44      45      46      47      48      49
    50      51Over Speed. Pls slow down.
            52Over Speed. Pls slow down.
            53Over Speed. Pls slow down.
            54Over Speed. Pls slow down.
            55Over Speed. Pls slow down.
            56Over Speed. Pls slow down.
            57Over Speed. Pls slow down.
            58Over Speed. Pls slow down. 
            59Over Speed. Pls slow down.
            60Over Speed. Pls slow down.
            61Over Speed. Pls slow down.
            62Over Speed. Pls slow down.
            63Over Speed. Pls slow down.
            64Over Speed. Pls slow down.
            65Over Speed. Pls slow down.
            66Over Speed. Pls slow down.
            67Over Speed. Pls slow down.
            68Over Speed. Pls slow down.
            69Over Speed. Pls slow down.
            70Over Speed. Pls slow down.

주의 - 최대 70까지 인쇄한 후 프로그램에서 객체 b가 사용되지 않는 경우에도 "class Bike에서 finalize method 호출..." 이후 JVM에 의해 b가 클리어되는지 여부가 불확실합니다."는 인쇄되지 않습니다.

finalize를 선택하면 클래스 생성용 카운트가 출력됩니다.

protected void finalize() throws Throwable {
    System.out.println("Run F" );
    if ( checkedOut)
        System.out.println("Error: Checked out");
        System.out.println("Class Create Count: " + classCreate);
}

주된

while ( true) {
    Book novel=new Book(true);
    //System.out.println(novel.checkedOut);
    //Runtime.getRuntime().runFinalization();
    novel.checkIn();
    new Book(true);
    //System.runFinalization();
    System.gc();

당신이 볼 수 있듯이.다음 출력은 클래스 카운트가 36일 때 gc가 처음 실행된 것을 나타냅니다.

C:\javaCode\firstClass>java TerminationCondition
Run F
Error: Checked out
Class Create Count: 36
Run F
Error: Checked out
Class Create Count: 48
Run F

최근 파이널라이저 방식(테스트 중에 접속 풀을 폐기하기 위해)과 씨름하고 있기 때문에 파이널라이저가 부족한 점이 많다고 말할 수 밖에 없습니다.VisualVM을 사용하여 관찰하고 실제 상호작용을 추적하기 위해 약한 참조를 사용하여 Java 8 환경(Oracle JDK, Ubuntu 15)에서 다음과 같은 사실이 확인되었습니다.

  • Finalizer(GC 부품)가 개별적으로 참조를 소유하는 즉시 Finalizer(완료)를 호출하지 않습니다.
  • 기본 Garbage Collector는 연결할 수 없는 개체를 풀링합니다.
  • Finalize는 가비지 컬렉터에 의해 리소스가 해방되는 특정 단계가 있음을 나타내는 구현 세부 정보를 나타내는 일괄 호출됩니다.
  • System.gc()를 호출해도 오브젝트가 완료되는 빈도는 높지 않습니다.Finalizer가 도달 불가능한 오브젝트를 보다 빠르게 인식할 수 있을 뿐입니다.
  • 스레드 덤프를 작성하면 거의 항상 히프 덤프 또는 기타 내부 메커니즘을 실행하는 동안 높은 히프 오버헤드로 인해 파이널라이저가 트리거됩니다.
  • 마무리 심은 메모리 요건(메모리의 여유 여유량) 또는 마무리 마크가 붙어 있는 오브젝트 리스트 중 하나에 의해 구속됩니다(내부 제한의 증가).따라서 완료되는 객체가 많은 경우 일부에 비해 완료 단계가 더 자주, 더 빨리 트리거됩니다.
  • System.gc()에 의해 직접 파이널이 트리거된 상황이 있었습니다.단, 참조가 로컬이고 짧은 경우만 해당됩니다.세대 관련일 수 있습니다.

최종 생각

Finalize 메서드는 신뢰할 수 없지만 한 가지 용도로만 사용할 수 있습니다.개체가 가비지 수집되기 전에 닫히거나 삭제되었는지 확인할 수 있으므로 수명 만료 작업이 포함된 보다 복잡한 수명 사이클을 가진 개체가 올바르게 처리되면 장애 방지 기능을 구현할 수 있습니다.그게 바로 내가 생각할 수 있는 유일한 이유야 그걸 무시하기 위한 가치가 있지

개체가 라이브 스레드 또는 정적 참조에서 연결할 수 없는 경우 개체는 가비지 컬렉션 또는 GC에 적합하게 됩니다. 즉, 모든 참조가 null인 경우 개체가 가비지 컬렉션에 적합하다고 할 수 있습니다.순환 종속성은 참조로 계산되지 않으므로 개체 A에 개체 B의 참조가 있고 개체 B에 개체 A의 참조가 있고 다른 라이브 참조가 없는 경우 개체 A와 B 모두 가비지 컬렉션에 적합합니다.일반적으로 오브젝트는 다음과 같은 경우에 Java에서 가비지를 수집할 수 있습니다.

  1. 해당 개체의 모든 참조가 null로 명시적으로 설정되었습니다(예: object = null).
  2. 오브젝트는 블록 내에 작성되며 컨트롤이 해당 블록을 종료하면 참조가 범위를 벗어납니다.
  3. 상위 개체가 null로 설정된 경우 개체가 다른 개체에 대한 참조를 보유하고 있고 컨테이너 개체의 참조를 null로 설정하면 하위 개체 또는 포함된 개체가 자동으로 가비지 수집의 대상이 됩니다.
  4. 개체에 WeakHashMap을 통한 라이브 참조만 있는 경우 가비지 수집에 적합합니다.

finalize 메서드는 보장되지 않습니다.오브젝트가 GC에 적합하게 되면 이 메서드가 호출됩니다.개체가 가비지 수집되지 않은 경우가 많습니다.

때때로 그것이 파괴될 때, 물체는 행동을 취해야 한다.예를 들어 개체에 파일 핸들이나 글꼴과 같은 비 Java 리소스가 있는 경우 개체를 삭제하기 전에 이러한 리소스가 해제되었는지 확인할 수 있습니다.이러한 상황을 관리하기 위해 java는 "finalizing"이라는 메커니즘을 제공합니다.개체를 완료하면 개체를 가비지 수집기에서 제거하려고 할 때 발생하는 특정 작업을 정의할 수 있습니다.클래스에 파이널라이저를 추가하려면 finalize() 메서드를 정의하기만 하면 됩니다.Java 실행 시간은 해당 클래스의 개체를 삭제하려고 할 때마다 이 메서드를 호출합니다.finalize method()에서는 오브젝트를 파기하기 전에 실행할 액션을 지정합니다.가비지 컬렉터는 더 이상 실행 상태를 참조하지 않거나 참조가 있는 다른 개체를 간접적으로 참조하지 않는 개체를 주기적으로 검색합니다.자산이 해방되기 전에 Java 런타임은 개체의 finalize() 메서드를 호출합니다.finalize() 메서드의 일반적인 형식은 다음과 같습니다.

protected void finalize(){
    // This is where the finalization code is entered
}

protected 키워드를 사용하면 클래스 밖에서 코드로 finalize()에 액세스할 수 없습니다.finalize()는 가비지 컬렉션 직전에 호출된다는 을 이해하는 것이 중요합니다.예를 들어 객체가 범위를 벗어나면 호출되지 않습니다., finalize()가 언제 실행될지 여부를 알 수 없습니다.그 결과 프로그램은 오브젝트가 사용하는 시스템자원 또는 기타 자원을 해방하기 위한 다른 수단을 제공해야 합니다.프로그램의 정상적인 실행에는 finalize()에 의존하지 마십시오.

최종 메서드를 재정의하는 클래스

public class TestClass {    
    public TestClass() {
        System.out.println("constructor");
    }

    public void display() {
        System.out.println("display");
    }
    @Override
    public void finalize() {
        System.out.println("destructor");
    }
}

최종 메서드가 호출될 가능성

public class TestGarbageCollection {
    public static void main(String[] args) {
        while (true) {
            TestClass s = new TestClass();
            s.display();
            System.gc();
        }
    }
}

메모리가 덤프 오브젝트로 오버로드되면 gc는 finalize 메서드를 호출합니다.

콘솔을 실행하여 Finalize 메서드가 자주 호출되지 않는 경우 메모리가 과부하되면 Finalize 메서드가 호출됩니다.

Java를 통해 오브젝트는 호출될 수 있는 finalize() 메서드를 구현할 수 있습니다.

finalize() 메서드는 가비지 컬렉터가 오브젝트를 수집하려고 하면 호출됩니다.

가비지 컬렉터가 실행되지 않으면 메서드가 호출되지 않습니다.

가비지 컬렉터가 개체를 수집하지 못하고 실행을 시도하는 경우 다시 말하지만 메서드는 두 번째 호출되지 않습니다.

실제로 실제 프로젝트에서 이 기능을 사용할 가능성은 매우 낮습니다.

호출되지 않을 수도 있고 두 번 호출되지 않을 수도 있다는 점을 명심하십시오.finalize() 메서드는 0 또는 1회 실행할 수 있습니다.

다음 코드에서 finalize() 메서드는 프로그램을 실행해도 가비지 컬렉터를 실행할 필요가 있기 전에 프로그램이 종료되므로 출력을 생성하지 않습니다.

원천

finalize()가비지 수집 직전에 호출됩니다.개체가 범위를 벗어나면 호출되지 않습니다.인지, 인지 알 수 입니다.finalize()행됩니니다다

예제:

이 종료된 .finalize()실행되지 않습니다.따라서 프로그램이 정상 작동에서 사용하는 수단이 아니라 다른 리소스를 올바르게 처리하기 위한 백업 절차 또는 특수 용도 응용 프로그램용으로 사용해야 합니다.

https://wiki.sei.cmu.edu/confluence/display/java/MET12-J.+Do+not+use+finalizers,에서 지적한 바와 같이

실행 시간은 Java Virtual Machine(JVM; Java 가상 머신)에 따라 다르기 때문에 최종자를 실행해야 하는 시간은 정해져 있지 않습니다.유일한 보증은 관련된 오브젝트가 도달할 수 없게 된 후(가비지 수집의 첫 번째 사이클 중 감지됨)와 가비지 수집기가 관련 오브젝트의 스토리지를 회수하기 전(가비지 수집기의 두 번째 사이클 중)에 실행된다는 것입니다.오브젝트 피니셔 실행은 오브젝트가 도달할 수 없게 된 후 임의의 시간 동안 지연될 수 있습니다.따라서 오브젝트의 finalize() 메서드에서 파일핸들을 닫는 등의 중요한 기능을 호출하는 것은 문제가 됩니다.

JDK의 최신 뉴스 18

openjdk 18에 의해 제공되는 JEPS 421에 따르면, 최종화와 그에 따른 기능은finalize() 방법은 '하다'로 됩니다.deprecated(forRemoval=true) 1818 이후 삭제가 합니다.

옵션jdk 18 입니다.--finalization=disabled는 jdk 자체의 내부 선언에서도 모든 곳에서 최종화 메커니즘을 디세블로 합니다.

이것은, 삭제가 계획되고 있는 이유에는, 몇개의 중대한 결함이 포함되어 있기 때문에, 여기서의 이 질문과도 관련이 있습니다.이러한 결함 중 하나는 객체가 도달할 수 없는 순간부터 최종자가 호출되는 순간까지 매우 오랜 시간이 걸릴 수 있다는 것입니다.또한 GC는 파이널라이저가 호출되는 것을 보증하지 않습니다.

이 프로그램을 실행하여 보다 잘 이해하십시오.

public class FinalizeTest 
{       
    static {
        System.out.println(Runtime.getRuntime().freeMemory());
    }

    public void run() {
        System.out.println("run");
        System.out.println(Runtime.getRuntime().freeMemory());
    }

     protected void finalize() throws Throwable { 
         System.out.println("finalize");
         while(true)
             break;          
     }

     public static void main(String[] args) {
            for (int i = 0 ; i < 500000 ; i++ ) {
                    new FinalizeTest().run();
            }
     }
}

언급URL : https://stackoverflow.com/questions/2506488/when-is-the-finalize-method-called-in-java

반응형