programing

자바 파괴자가 있나요?

goodsources 2022. 8. 13. 12:29
반응형

자바 파괴자가 있나요?

자바 파괴자가 있나요?저는 이것에 관한 문서를 찾을 수 없을 것 같습니다.없다면 어떻게 같은 효과를 얻을 수 있을까요?

질문을 좀 더 구체적으로 하기 위해 데이터를 다루는 애플리케이션을 작성 중인데, 사양에는 애플리케이션을 처음 실행한 상태로 되돌리는 '리셋' 버튼이 있어야 한다고 되어 있습니다.그러나 응용 프로그램을 닫거나 재설정 버튼을 누르지 않는 한 모든 데이터는 '라이브' 상태여야 합니다.

보통 C/C++ 프로그래머이기 때문에 구현이 간단하다고 생각했습니다.(그래서 마지막으로 구현하려고 했습니다.)리셋 버튼을 눌렀을 때 모든 '리셋 가능한' 오브젝트가 같은 클래스에 있도록 프로그램을 구성했습니다.

데이터를 참조해 가비지 콜렉터가 수집하기를 기다리는 것 뿐이라면, 사용자가 데이터를 입력하고 리셋 버튼을 반복해서 누르면 메모리 누수가 발생하지 않을까 생각했습니다.또 자바가 언어로서 상당히 성숙해 있기 때문에, 이것을 방지하거나 우아하게 대처하는 방법이 있을 것이라고 생각하고 있습니다.

Java는 가비지 수집 언어이기 때문에 개체가 언제 파괴될지 예측할 수 없습니다.그러므로 파괴자와 직접 동등한 존재는 없다.

라고 하는 상속된 방법이 있습니다.finalize단, 이것은 완전히 가비지 콜렉터의 재량에 따라 호출됩니다.따라서 명시적으로 정리할 필요가 있는 클래스의 경우 close 메서드를 정의하고 건전성 체크에만 finalize를 사용합니다(close가 호출되지 않은 경우 즉시 실행하고 오류를 기록합니다).

최근 최종 결정에 대한 심도 있는 논의가 이루어졌기 때문에, 필요하다면 더 심도 있는 질문을 할 수 있을 것입니다.

리소스 사용 설명문을 확인하십시오.예를 들어 다음과 같습니다.

try (BufferedReader br = new BufferedReader(new FileReader(path))) {
  System.out.println(br.readLine());
} catch (Exception e) {
  ...
} finally {
  ...
}

여기서 더 이상 필요하지 않은 리소스는BufferedReader.close()방법.를 실장하는 독자적인 클래스를 작성할 수 있습니다.AutoCloseable비슷한 방법으로 사용할 수 있습니다.

이 문장은 다음보다 더 제한적입니다.finalize코드 구조화 측면에서 보면, 동시에 코드를 이해하고 유지하기가 더 쉬워집니다.또, 그 보증은 없습니다.finalize응용 프로그램 라이브 타임 중에 메서드가 호출됩니다.

아니, 여기 파괴자는 없어그 이유는 모든 Java 객체가 히프가 할당되어 가비지가 수집되기 때문입니다.명시적 할당 해제 없음(즉,C++의 delete 연산자)는 실제 파괴자를 구현하는 합리적인 방법이 없습니다.

Java는 피니셔를 지원하지만 소켓, 파일 핸들, 창 핸들 등과 같은 네이티브 리소스에 대한 핸들을 유지하는 개체의 보호 수단으로만 사용됩니다.가비지 콜렉터는 피니셔 없이 객체를 수집하면 메모리 영역을 빈 상태로 표시하기만 하면 됩니다.오브젝트에 파이널라이저가 있는 경우 오브젝트는 먼저 임시 위치에 복사되고(여기서는 가비지 수집 중임을 기억하십시오), 다음으로 파이널라이저 스레드가 파이널라이저 대기 큐에 큐잉되어 매우 낮은 priority로 큐를 폴링하여 파이널라이저를 실행합니다.

애플리케이션이 종료되면 보류 중인 객체가 완료될 때까지 기다리지 않고 JVM이 중지되므로 최종자가 실행된다는 보장은 거의 없습니다.

finalize() 메서드의 사용은 피해야 합니다.이들은 신뢰할 수 있는 리소스 정리 메커니즘이 아니며 이를 남용하여 가비지 컬렉터에 문제를 일으킬 수 있습니다.

오브젝트에 할당 해제 콜이 필요한 경우(리소스를 해방하는 경우 등), 명시적인 메서드콜을 사용합니다.이 규칙은 기존 API(: Closeable, Graphics.dispose(), Widget.dispose())에서 볼 수 있으며 보통 try/finally를 통해 호출됩니다.

Resource r = new Resource();
try {
    //work
} finally {
    r.dispose();
}

폐기된 개체를 사용하려고 하면 런타임 예외가 발생합니다(IllogalStateException 참조).


편집:

데이터를 참조해 가비지 콜렉터가 수집하기를 기다리는 것 뿐이라면, 사용자가 데이터를 입력하고 리셋 버튼을 반복해서 누르면 메모리 누수가 발생하지 않을까 생각했습니다.

일반적으로 필요한 것은 오브젝트의 참조를 해제하는 것 뿐입니다.적어도 이렇게 동작해야 합니다.가비지 수집이 걱정되는 경우 Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning(또는 JVM 버전용 동등한 문서)을 참조하십시오.

Java 1.7이 출시됨에 따라 다음 옵션을 사용할 수 있게 되었습니다.try-with-resources블록. 예를 들어,

public class Closeable implements AutoCloseable {
    @Override
    public void close() {
        System.out.println("closing..."); 
    }
    public static void main(String[] args) {
        try (Closeable c = new Closeable()) {
            System.out.println("trying..."); 
            throw new Exception("throwing..."); 
        }
        catch (Exception e) {
            System.out.println("catching..."); 
        }
        finally {
            System.out.println("finalizing..."); 
        } 
    }
}

이 수업을 실행하면c.close()실행이 완료됩니다.try블록은 남겨져 있습니다.catch그리고.finally블록이 실행됩니다.의 경우와 달리finalize()방법,close()실행이 보증됩니다.단, 이 명령어를 명시적으로 실행할 필요는 없습니다.finally절을 클릭합니다.

나는 다른 답변에 전적으로 동의하며 최종 결정의 실행에 의존하지 말라고 말한다.

try-catch-finally 블록 외에 Runtime #addShutdown을 사용할 수 있습니다.프로그램에서 최종 정리를 수행하기 위해 후크(Java 1.3에서 도입)를 실행합니다.

이는 디스트럭터와 동일하지는 않지만 리스너 오브젝트가 등록되어 있는 셧다운 훅을 실장할 수 있습니다.이러한 셧다운 훅은 일반적으로 디스트럭터에서 실행되는 청소 메서드(영속적인 데이터베이스 연결 닫기, 파일 잠금 제거 등)를 호출할 수 있습니다.다시 말씀드리지만, 이것은 파괴자를 대체하는 것은 아니지만 경우에 따라서는 이것으로 원하는 기능에 접근할 수 있습니다.

이 방법의 장점은 프로그램의 나머지 부분과 느슨하게 결합되어 있는 디구성 동작을 할 수 있다는 것입니다.

아뇨, 그게 당신이 얻을 수 있는 가장 가까운 거에요.

단, 호출 시(및 호출 시)는 보증되지 않습니다.
참조:

첫째, Java는 가비지 컬렉션이기 때문에 오브젝트 파괴에 대해 아무것도 할 필요가 없는 경우가 드물다는 점에 유의하십시오.첫째, 일반적으로 해방되는 관리 리소스가 없기 때문에, 둘째, 언제 또는 언제 발생할지 예측할 수 없기 때문에 "아무도 내 개체를 사용하지 않는 즉시" 발생할 필요가 있는 작업에 적합하지 않습니다.

java.lang.ref를 사용하여 오브젝트가 파괴된 후 알림을 받을 수 있습니다.PhantomReference(실제로 파기되었다고 하는 것은 약간 부정확할 수 있지만, 해당 참조에 대한 팬텀이 큐잉되면 더 이상 복구할 수 없으며, 이는 보통 같은 것에 해당합니다.)일반적인 용도는 다음과 같습니다.

  • 클래스 내에서 파기할 필요가 있는 리소스를 다른 도우미 개체로 분리합니다(일반적인 경우처럼 연결을 닫기만 하면 새 클래스를 쓸 필요가 없습니다. 이 경우 닫히는 연결이 "도움말 개체"가 됩니다).
  • 주 객체를 작성할 때 주 객체에 대한 PhantomReference도 작성합니다.이를 통해 새 도우미 개체를 참조하거나 PhantomReference 개체에서 대응하는 도우미 개체로의 맵을 설정합니다.
  • 메인 오브젝트가 수집되면 PhantomReference가 큐잉됩니다(또는 큐잉될 수도 있습니다).파이널라이저와 마찬가지로 VM이 종료되면 대기하지 않습니다).큐를 처리하고 있는지 확인합니다(특수 스레드 또는 때때로).도우미 개체에 대한 하드 참조로 인해 도우미 개체가 아직 수집되지 않았습니다.따라서 도우미 개체에서 원하는 정리를 수행한 후 PhantomReference를 삭제하면 도우미도 수집됩니다.

destructor처럼 보이지만 destructor처럼 동작하지 않는 finalize()도 있습니다.보통은 좋은 선택이 아닙니다.

finalize()함수는 파괴자입니다.

다만, GC 후에 호출되어 언제(있을 경우)가 발생할지 알 수 없기 때문에, 통상은 사용하지 말아 주세요.

또, 1개 이상의 GC가 필요합니다.이러한 오브젝트의 할당을 해제해야 합니다.finalize().

코드내의 논리적인 장소에서는, 다음과 같은 방법으로 실시할 필요가 있습니다.try{...} finally{...}스테이트먼트!

나는 대부분의 대답에 동의한다.

어느 쪽에도 전적으로 의존해서는 안 됩니다.finalize또는ShutdownHook

마무리짓다

  1. JVM은 이 타이밍을 보증하지 않습니다.finalize()메서드가 호출됩니다.

  2. finalize()는 GC 스레드에 의해1회만 호출됩니다.오브젝트가 최종 메서드에서 회복되면finalize다시 호출되지 않습니다.

  3. 응용 프로그램에 가비지 컬렉션이 호출되지 않는 활성 개체가 있을 수 있습니다.

  4. 조금도ExceptionGC 스레드에 의해 무시됩니다.

  5. System.runFinalization(true)그리고.Runtime.getRuntime().runFinalization(true)메서드는 호출 가능성을 높입니다.finalize()이 두 가지 방법은 더 이상 사용되지 않습니다.이러한 방법은 스레드의 안전성이 부족하고 데드록이 발생할 수 있으므로 매우 위험합니다.

셧다운

public void addShutdownHook(Thread hook)

새 가상 시스템 종료 후크를 등록합니다.

Java 가상 시스템은 다음 두 가지 이벤트에 대해 종료됩니다.

  1. 프로그램은 데몬이 아닌 마지막 스레드가 종료되거나 종료될 때 정상적으로 종료됩니다(따라서,System.exit) 메서드가 호출됩니다.

  2. ^C 입력과 같은 사용자 인터럽트 또는 사용자 로그오프 또는 시스템 종료와 같은 시스템 전체 이벤트에 대한 응답으로 가상 시스템이 종료됩니다.

  3. 셧다운 후크는 단순히 초기화되었지만 시작되지 않은 스레드입니다.가상 시스템이 종료 시퀀스를 시작하면 등록된 모든 종료 후크가 지정되지 않은 순서로 시작되고 동시에 실행되도록 합니다.모든 후크가 완료되면 종료 시 완료가 활성화된 경우 호출되지 않은 모든 최종자가 실행됩니다.

  4. 마지막으로 가상 시스템이 중지됩니다.종료 메서드를 호출하여 셧다운이 시작된 경우 데몬 스레드는 셧다운 시퀀스 중에도 계속 실행됩니다.

  5. 셧다운 후크도 신속하게 작업을 완료해야 합니다.프로그램이 exit을 호출하면 가상 시스템이 즉시 종료되고 종료됩니다.

    그러나 Oracle 문서에서도 이를 인용하고 있습니다.

드문 경우지만 가상 시스템이 중단될 수 있습니다. 즉, 완전히 종료되지 않고 실행을 중지할 수 있습니다.

이 문제는 가상 시스템이 외부에서 종료될 때(예:SIGKILL Unix의 TerminateProcessMicrosoft Windows の microsoft microsoft microsoft microsoft microsoft microsoft 。네이티브 메서드가 내부 데이터 구조를 손상시키거나 존재하지 않는 메모리에 액세스하려는 경우와 같이 잘못된 경우에도 가상 시스템이 중단될 수 있습니다.가상 시스템이 중단되면 종료 후크를 실행할지 여부를 보장할 수 없습니다.

결론: 블록을 적절히 사용하고 중요한 자원을 블록으로 방출한다. 블록, 캐치 및 리소스 릴리스 중.

만약 그것이 단지 당신이 걱정하는 기억이라면, 하지 마세요.GC만 믿어줘 괜찮은 일을 할 수 있어.실제로 매우 효율적이기 때문에 경우에 따라서는 대규모 어레이를 사용하는 것보다 다수의 작은 개체를 생성하는 것이 성능에 더 좋을 수 있습니다.

아마 한번 써보실 수 있을 거예요.finally block을 사용하여 오브젝트를 사용하고 있는 제어 흐름에서 오브젝트를 확정합니다.물론 자동으로 발생하는 것은 아니지만 C++에서의 파괴도 아닙니다.최종 블록에서 리소스가 닫히는 경우가 많습니다.

Lombok에는 C++ 디스트럭터와 거의 유사한 @Cleanup 주석이 있습니다.

@Cleanup
ResourceClass resource = new ResourceClass();

은 () Lombok을 합니다.try-finallyresource.close()는 실행이 변수의 범위를 벗어나면 호출됩니다. 리소스 해방 방법)을 도 있습니다.resource.dispose()

@Cleanup("dispose")
ResourceClass resource = new ResourceClass();

Java 디스트럭터에 가장 가까운 것은 finalize() 메서드입니다.전통적인 파괴자의 큰 차이점은 언제 호출될지 모른다는 것입니다. 왜냐하면 그것은 쓰레기 수집가의 책임이기 때문입니다.파일 핸들 등의 일반적인 RAIA 패턴은 finalize()에서는 신뢰성 있게 동작하지 않기 때문에 사용하기 전에 주의 깊게 읽어 두는 것이 좋습니다.

원래 질문만 생각해도...다른 모든 학습된 답변에서 결론을 내릴 수 있을 것 같습니다.또한 Bloch의 Effective Java, item 7 "Avoid finalizers"에서 Java 언어에 부적절한 방법으로 합법적인 질문에 대한 해결책을 찾고 있습니다.:

...OP가 실제로 원하는 것은 리셋할 필요가 있는 모든 오브젝트를 일종의 "플레이펜"으로 유지하는 것입니다.리셋할 수 없는 오브젝트는 모두 일종의 접근자 오브젝트를 통해서만 참조할 수 있습니다.

그런 다음 기존 플레이펜의 연결을 해제하고 새 플레이펜을 만듭니다.플레이펜 내의 모든 오브젝트 웹이 떨어져 나간 후 다시 돌아오지 않고 GC에 의해 하루 동안 수집됩니다.

중 가 「」인 .Closeable안 되지만) ( 안 된다.close method에 수 .Bag때한 한 때), 사람의 은 모든 을입니다.Closeables 닫는다...?

코드는 다음과 같습니다.

accessor.getPlaypen().closeCloseables();
accessor.setPlaypen( new Playpen() );

closeCloseables는 아마도 "Latch"와 관련된 블로킹일 수 있습니다.CountdownLatch)Runnables/CallablesPlaypenJavaFX의 경우, JavaFX는 JavaFX로 변환.

여기에는 좋은 답변이 많이 있습니다만, finalize()사용하지 않는 이유에 대해 몇 가지 추가 정보가 있습니다.

이 "Da"로 System.exit() ★★★★★★★★★★★★★★★★★」Runtime.getRuntime().exit()디폴트로는 피니셔는 실행되지 않습니다.자바독에서 Runtime.exit():

가상 시스템의 종료 시퀀스는 두 단계로 구성됩니다.첫 번째 단계에서는 등록된 모든 셧다운 훅(있는 경우)은 지정되지 않은 순서로 시작되며 완료될 때까지 동시에 실행할 수 있습니다.두 번째 단계에서는 종료 시 완료가 활성화된 경우 호출되지 않은 모든 최종자가 실행됩니다.이 작업이 완료되면 가상 시스템이 중지됩니다.

전화는 할 수 있지만, 「미결의 모든 최종판정을 완료하기 위한 최선의 노력」만 할 뿐, 보증은 할 수 없습니다.

방법은 있지만 사용하지 마십시오. 안전하지 않고 오래 전에 사용되지 않았습니다.

Java 애플릿을 작성할 경우 애플릿 "destroy()" 메서드를 덮어쓸 수 있습니다.그건...

 * Called by the browser or applet viewer to inform
 * this applet that it is being reclaimed and that it should destroy
 * any resources that it has allocated. The stop() method
 * will always be called before destroy().

분명히 당신이 원하는 게 아니라 다른 사람들이 찾고 있는 것일 수도 있어요.

Java의 GC 테크놀로지에 상당한 발전이 있었지만, 여전히 레퍼런스에 유의할 필요가 있습니다.겉보기에는 사소한 참조 패턴의 수많은 사례들이 떠오르는데, 실제로 후드 아래에 쥐 둥지를 튼다.

게시물에서는 객체 재사용을 위해 리셋 방법을 구현하려는 것처럼 보이지 않습니다(참?).오브젝트에 정리해야 할 다른 유형의 자원(닫아야 할 스트림, 반환해야 할 풀링된 객체 또는 대여된 객체)이 있습니까?메모리 할당 해제만 걱정된다면 오브젝트 구조를 재검토하여 오브젝트가 GC 시에 정리되는 자기포함 구조인지 확인합니다.

파괴자가 없는 Java는 없습니다.Java의 이면에 있는 주된 이유는 항상 백그라운드에서 수동적으로 동작하는 가비지 콜렉터이며 모든 오브젝트는 힙메모리(GC가 동작하는 장소)로 작성됩니다.c++에서는 Garbage Collector와 같은 것이 없기 때문에 삭제 함수를 명시적으로 호출해야 합니다.

Java에서는 가비지 컬렉터가 사용되지 않는 개체를 자동으로 삭제하여 메모리를 비웁니다.그래서 자바는 파괴자가 없는 것이 현명하다.

안드로이드 프로그래밍의 경우 onDestroy() 메서드를 호출해 보십시오.이것은 Activity/Service 클래스가 종료되기 직전에 실행된 마지막 메서드입니다.

방금 스캔한 모든 답변에서 누락된 것이 결승선 대신 안전한 답변입니다.다른 모든 답변은 신뢰할 수 없고 현재 사용되지 않으므로 리소스 사용 및 피니셔 회피에 대한 올바른 답변입니다.

하지만 그들은 클리너에 대해 언급하지 않았다.정리 작업을 최종자보다 더 나은 방법으로 명시적으로 처리하기 위해 Java 9에 정리자가 추가되었습니다.

https://docs.oracle.com/javase/9/docs/api/java/lang/ref/Cleaner.html

Weld 의 Contexts and Dependency Injection(CDI; 컨텍스트 및 의존성 주입) 프레임워크를 사용할 경우 Java 주석 @Predestroy를 사용하여 정리 작업을 수행할 수 있습니다.

@javax.enterprise.context.ApplicationScoped
public class Foo {

  @javax.annotation.PreDestroy
  public void cleanup() {
    // do your cleanup    
  }
}

Java에는 정확히 destructor 클래스가 없습니다.클래스는 가비지 콜렉터에 의해 Java에서 자동으로 파괴됩니다.다만, 다음의 것을 사용해 실행할 수 있습니다만, 완전히 같은 것은 아닙니다.

finish()

최종판정에 대한 심도 있는 논의를 낳는 질문이 있었습니다.필요에 따라서는, 보다 심도 있는 설명을 얻을 수 있습니다.

저는 주로 C++를 취급하고 있었기 때문에 파괴자를 찾게 되었습니다.저는 지금 JAVA를 많이 사용하고 있습니다.내가 한 일은 모두에게 최선의 경우는 아니지만 함수를 통해 모든 값을 0 또는 디폴트로 리셋함으로써 나만의 소멸자를 구현했다.

예:

public myDestructor() {

variableA = 0; //INT
variableB = 0.0; //DOUBLE & FLOAT
variableC = "NO NAME ENTERED"; //TEXT & STRING
variableD = false; //BOOL

}

이상적으로는 이 방법이 모든 상황에서 작동하는 것은 아니지만, 글로벌 변수가 있는 경우에는 변수가 많지 않은 한 사용할 수 있습니다.

내가 최고의 자바 프로그래머는 아니지만, 그것은 나에게 효과가 있는 것 같다.

언급URL : https://stackoverflow.com/questions/171952/is-there-a-destructor-for-java

반응형