왜 finalize ()를 구현하겠습니까?


371

나는 많은 신인 Java 질문을 읽었 finalize()으며 아무도 finalize ()가 리소스를 정리하는 신뢰할 수없는 방법이라는 것을 아무도 분명히 알지 못했다는 것을 알게되었습니다. 누군가 Connections를 정리하는 데 사용한다는 의견을 보았습니다 .Connection이 닫혔다는 보장에 가까워 질 수있는 유일한 방법은 마침내 try (catch)를 구현하는 것이므로 정말 무섭습니다.

CS에서 교육을받지는 않았지만 지금은 거의 10 년 동안 전문적으로 Java 프로그래밍을 해왔으며 구현 한 사람을 본 적이 없습니다. finalize() 프로덕션 시스템에서 하는 적이 없습니다. 그렇다고해서 그것이 용도가 없거나 내가 함께 일한 사람들이 올바르게하고 있다는 것을 의미하지는 않습니다.

그래서 제 질문은 어떤 유스 케이스가 구현에 있는지입니다. finalize() 언어 내의 다른 프로세스 또는 구문을 통해보다 안정적으로 처리 할 수없는 을 있습니까?

Java 교과서를 반복하거나 특정 시나리오 나 경험을 제공하십시오. 그렇지 않으면이 질문의 의도가 아닌 finalize의 의도 된 용도로는 충분하지 않습니다.


안녕 finalize () 방법은 여기에 잘 설명 howtodoinjava.com/2012/10/31/…
Sameer Kazi

2
대부분의 응용 프로그램 및 라이브러리 코드는 절대 사용하지 않습니다 finalize(). 그러나 호출자를 대신하여 네이티브 리소스를 관리하는와 같은 플랫폼 라이브러리 코드SocketInputStream 는 리소스 누수의 위험을 최소화하기 위해 시도합니다 (또는 PhantomReference나중에 추가 된 등의 동일한 메커니즘을 사용 합니다). 개발자의 99.9999 %가 결코 개발자를 쓰지 않더라도 말입니다.
Brian Goetz 1

답변:


231

외부 리소스 (소켓, 파일 등)를 보유한 객체의 백스톱으로 사용할 수 있습니다. close()호출해야하는 메소드 및 문서를 구현하십시오 .

처리가 완료되지 않은 것으로 감지 finalize()되면 close()처리를 구현 하십시오 . 아마도 stderr버그가있는 발신자를 청소하고 있음을 지적 하기 위해 무언가를 버려 두었을 수도 있습니다.

예외적이거나 번잡 한 상황에서 추가 안전을 제공합니다. 모든 발신자가 매번 올바른 일을하는 것은 아닙니다 try {} finally {}. 불행히도 대부분의 환경에서 적용됩니다.

거의 필요하지 않다는 데 동의합니다. 그리고 논평자들이 지적한 바와 같이, 그것은 GC 오버 헤드와 함께 온다. 장기 실행 앱에서 "벨트 및 멜빵"안전이 필요한 경우에만 사용하십시오.

Java 9 Object.finalize()부터는 더 이상 사용되지 않습니다. 그들은 우리를 지적 java.lang.ref.Cleaner하고 java.lang.ref.PhantomReference대안으로.


44
finalize ()에 의해 예외가 발생하지 않도록하십시오. 그렇지 않으면 가비지 수집기가 해당 객체를 계속 정리하지 않으므로 메모리 누수가 발생합니다.
skaffman

17
Finalize가 호출되는 것은 보장되지 않으므로 리소스를 공개한다고 믿지 마십시오.
17:14에

19
skaffman-믿지 않습니다 (버그가 많은 JVM 구현 제외). Object.finalize () javadoc에서 : finalize 메소드에서 포착되지 않은 예외가 발생하면 예외가 무시되고 해당 오브젝트의 종료가 종료됩니다.
John M

4
당신의 제안은 오랫동안 사람들의 버그를 숨길 수 있습니다. 나는 그렇게하지 않는 것이 좋습니다.
kohlerm

64
나는이 정확한 이유로 마무리를 실제로 사용했습니다. 코드를 물려 받았으며 매우 버그가 많았으며 데이터베이스 연결을 열어 두는 경향이있었습니다. 연결 시간과 위치에 대한 데이터를 포함하도록 연결을 수정 한 다음 연결이 올바르게 닫히지 않은 경우이 정보를 기록하도록 마무리를 구현했습니다. 닫히지 않은 연결을 추적하는 데 큰 도움이되었습니다.
brainimus

174

finalize()지정되지 않은 시간에 코드를 실행하는 것이 좋을 수도 있다는 JVM에 대한 힌트입니다. 이것은 코드가 신비하게 실행되지 않도록하려는 경우에 좋습니다.

파이널 라이저에서 중요한 것을 수행하는 것 (기본적으로 로깅을 제외한 모든 것)도 세 가지 상황에서 좋습니다.

  • 다른 최종 객체는 여전히 프로그램의 나머지 부분이 유효한 것으로 간주됩니다.
  • 종료 후 모든 클래스의 모든 메소드에 많은 검사 코드를 추가하여 종료 후 올바르게 작동하는지 확인하려고합니다.
  • 실수로 완성 된 개체를 부활 시키려고하고, 왜 작동하지 않는지, 그리고 / 또는 결국 릴리스 될 때 왜 끝나지 않는지를 알아 내려고 많은 시간을 할애합니다.

finalize ()가 필요하다고 생각되면 때로는 팬텀 참조가 필요합니다 (이 예제에서는 참조에 의해 사용되는 연결에 대한 하드 참조를 보유하고 팬텀 참조가 대기 한 후에 닫을 수 있습니다). 이것은 또한 신비하게도 절대로 실행되지 않을 수있는 속성을 가지고 있지만 적어도 최종 객체에서 메소드를 호출하거나 부활시킬 수는 없습니다. 따라서 연결을 깨끗하게 닫을 필요는 없지만 상황이 좋을 때도 좋을 것입니다. 클래스의 고객은 직접 연락을 할 수 없거나 전화를 걸 수 없습니다 (실제로 공평합니다- 뭐' s 수집하기 전에 특정 조치 가 필요한 인터페이스를 설계하는 경우 가비지 콜렉터가 전혀 필요하지 않습니까? 그것은 malloc / free의 시대에 우리를 되돌려 놓는다.)

다른 경우에는 관리하려는 리소스가 더 강력해야합니다. 예를 들어, 왜 해당 연결을 닫아야합니까? 궁극적으로 시스템에서 제공하는 일종의 I / O (소켓, 파일 등)를 기반으로해야하는데, 왜 가장 낮은 수준의 리소스를 확보 할 때 시스템을 닫아 시스템을 닫을 수 없습니까? 다른 쪽 끝의 서버에서 소켓을 떨어 뜨리지 않고 연결을 완전히 닫아야하는 경우 코드가 실행중인 시스템의 전원 케이블을 통해 누군가가 트립되거나 중재 네트워크가 종료되면 어떻게됩니까?

면책 조항 : 나는 과거에 JVM 구현에 종사했습니다. 나는 파이널 라이저가 싫어.


76
극단적 인 풍자적 정의를지지합니다.
Perception

32
이것은 질문에 대답하지 않습니다. 그것은 finalize()누군가가 실제로 그것을 사용하기를 원하는 이유를주지 않고의 모든 단점을 말합니다 .
기계 달팽이

1
@supercat : 팬텀 레퍼런스 (그 ​​문제에 대한 모든 레퍼런스)가 Java 2에 도입되었습니다
Steve Jessop

1
@ supercat : 미안 네, "참조"라는 의미 java.lang.ref.Reference와 하위 클래스. Java 1에는 변수가 있습니다 :-) 그리고 예, 종결 자도 있습니다.
Steve Jessop

2
@SteveJessop : 기본 클래스 생성자가 다른 엔티티가 생성중인 객체 (일반적인 패턴)를 대신하여 상태를 변경하도록 요청하지만 파생 클래스 필드 초기화 프로그램에서 예외가 발생하면 부분적으로 구성된 객체가 즉시 정리되어야합니다. 그 후에는 (즉, 외부 엔티티에 서비스를 더 이상 필요로하지 않는다고 알린다), Java 나 .NET은 이로 인해 발생할 수있는 완전히 깨끗한 패턴을 제공하지 않습니다. 실제로, 그들은 정리 코드에 도달하기 위해 정리가 필요한 것에 대한 참조를 어렵게 만드는 길을 벗어난 것처럼 보입니다.
supercat

58

간단한 규칙 : 종료자를 사용하지 마십시오.

객체가 finalizer를 가지고 있다는 사실만으로 (실행 코드에 관계없이) 가비지 수집에 상당한 오버 헤드가 발생하기에 충분합니다.

Brian Goetz 의 기사 에서 :

종료자가있는 객체 (사소한 finalize () 메서드가있는 객체)는 종료자가없는 객체와 비교하여 상당한 오버 헤드가 있으므로 드물게 사용해야합니다. 최종화 가능 객체는 할당 속도가 느리고 수집 속도가 느립니다. 할당시 JVM은 완료 가능 오브젝트를 가비지 콜렉터에 등록해야하며 (최소한 HotSpot JVM 구현에서) 완료 가능 오브젝트는 대부분의 다른 오브젝트보다 느린 할당 경로를 따라야합니다. 마찬가지로, 최종화 가능한 객체도 수집 속도가 느립니다. 종료 가능한 객체를 회수하려면 가비지 수집주기가 2 회 이상 (가장 좋은 경우) 필요하며 가비지 수집기는 마무리 작업을 호출하기 위해 추가 작업을 수행해야합니다. 도달 할 수없는 최종화 가능 오브젝트가 사용하는 메모리가 더 오래 유지되므로 오브젝트를 할당하고 수집하는 데 더 많은 시간이 걸리고 가비지 콜렉터에 더 많은 압력이 가해집니다. 이를 파이널 라이저가 예측 가능한 기간 또는 전혀 실행하지 않을 수 있다는 사실과 결합하면 최종화가 올바른 도구로 사용되는 상황이 상대적으로 적다는 것을 알 수 있습니다.


46

프로덕션 코드에서 마무리 작업을 사용한 유일한 시간은 주어진 객체의 리소스가 정리되었는지 확인하고 그렇지 않은 경우 매우 성가신 메시지를 기록하는 것입니다. 실제로 시도하지 않았고 제대로 수행되지 않으면 크게 외쳤습니다. 매우 유용한 것으로 판명되었습니다.


35

1998 년부터 전문적으로 Java를 해왔으며 구현 한 적이 없습니다 finalize(). 한 번도 아닙니다.


그렇다면 공개 클래스 객체를 어떻게 파괴합니까? ADF에 문제가 있습니다. 기본적으로는 (API를 신선한 데이터를 가져 오는) 페이지를 다시로드한다고 가정하지만 그것은 기존의 객체를 복용하고 결과를 보여주는 것
InfantPro'Aravind '

2
@ InfantPro'Aravind '호출 finalize는 객체를 제거하지 않습니다. 가비지가 객체를 수집하는 경우와시기에 JVM이 호출하도록 선택할 수있는 방법입니다.
Paul Tomblin

@PaulTomblin, 세부 사항에 감사드립니다. ADF에서 페이지를 새로 고칠 제안이 있습니까?
InfantPro'Aravind '

@ InfantPro'Aravind 'ADF를 사용한 적이 없습니다.
Paul Tomblin

28

받아 들인 대답은 좋았습니다. 지금은 실제로 전혀 사용하지 않고 마무리 기능을 가질 수있는 방법이 있다고 덧붙였습니다.

"참조"클래스를보십시오. 약한 참조, 팬텀 참조 및 소프트 참조.

그것들을 사용하여 모든 객체에 대한 참조를 유지할 수는 있지만이 참조는 GC를 중지시키지 않습니다. 이것에 대한 깔끔한 점은 삭제 될 때 메소드를 호출하도록 할 수 있으며이 메소드 가 호출 되도록 보장 할 수 있다는 것입니다.

마무리에 관해서 : 어떤 객체가 해제되었는지 이해하기 위해 finalize를 한 번 사용했습니다. 스태틱, 레퍼런스 카운팅 등을 사용하여 깔끔한 게임을 할 수는 있지만 분석만을위한 것이지만 다음과 같은 코드를주의해서 살펴보십시오 (마지막뿐만 아니라 가장 가능성이 높은 곳).

public void finalize() {
  ref1 = null;
  ref2 = null;
  othercrap = null;
}

누군가 자신이하는 일을 몰랐다는 신호입니다. 이와 같은 "정리"는 거의 필요하지 않습니다. 수업이 GC되면 자동으로 이루어집니다.

마무리에서 이와 같은 코드를 찾으면 코드를 작성한 사람이 혼란스러워 할 것입니다.

다른 곳이라면 코드가 잘못된 모델에 대한 유효한 패치 일 수 있습니다 (클래스는 오랫동안 머물러 있고 어떤 이유로 든 객체가 GC되기 전에 수동으로 해제해야했습니다). 일반적으로 누군가 리스너 또는 무언가를 제거하는 것을 잊어 버렸고 왜 객체가 GC가 아닌지 알아낼 수 없기 때문에 참조하는 것을 삭제하고 어깨를 으 walk하고 멀리합니다.

"Quicker"를 정리하는 데 사용해서는 안됩니다.


3
팬텀 참조는 어떤 객체가 해제되는지 추적하는 더 좋은 방법입니다.
Bill Michell

2
내가 들어 본 "약한 참조"에 대한 최고의 설명을 제공하기위한 투표.
sscarduzio

유감스럽게도이 책을 읽는 데 오랜 세월이 걸렸지 만 실제로 답변에 추가 할 수 있습니다.
스펜서 Kormos

27

이걸로 무엇을 만들 수 있을지 모르겠지만 ...

itsadok@laptop ~/jdk1.6.0_02/src/
$ find . -name "*.java" | xargs grep "void finalize()" | wc -l
41

내가 추측 그래서 태양은 발견 일부 가 사용되어야한다 (그들이 생각하는) 경우를.


12
"Sun 개발자가 항상 옳을 까"라는 질문이기도합니까?
CodeReaper

13
그러나 finalize실제로 사용하는 대신 지원을 구현하거나 테스트하는 용도는 몇 개 입니까?
기계 달팽이

나는 Windows를 사용합니다. Windows에서 어떻게 같은 일을 하시겠습니까?
gparyani

2
@damryfbfnetsi : chocolatey.org/packages/ack를 통해 ack ( beyondgrep.com )을 설치하십시오 . 또는의 파일에서 찾기 기능을 사용하십시오 . $FAVORITE_IDE
Brian Cline

21
class MyObject {
    Test main;

    public MyObject(Test t) {    
        main = t; 
    }

    protected void finalize() {
        main.ref = this; // let instance become reachable again
        System.out.println("This is finalize"); //test finalize run only once
    }
}

class Test {
    MyObject ref;

    public static void main(String[] args) {
        Test test = new Test();
        test.ref = new MyObject(test);
        test.ref = null; //MyObject become unreachable,finalize will be invoked
        System.gc(); 
        if (test.ref != null) System.out.println("MyObject still alive!");  
    }
}

=====================================

결과:

This is finalize

MyObject still alive!

======================================

따라서 finalize 방법으로 연결할 수없는 인스턴스에 도달 할 수 있습니다.


21
어떤 이유로,이 코드는 좀비 영화를 생각하게합니다. 당신은 당신의 물건을 GC하고 다시 일어납니다 ...
steveha

위의 좋은 코드입니다. 지금 객체를 다시 연결할 수있게 만드는 방법이 궁금합니다.
lwpro2 2016 년

15
아니요, 위의 잘못된 코드입니다. finalize가 나쁜 이유의 예입니다.
Tony

이 호출은 기억 System.gc();가비지 수집기가 실제로 실행하는 것은 아닙니다. 힙을 정리하는 것이 GC의 완전한 재량입니다 (여전히 충분한 여유 힙이 있거나 조각화되지 않았을 수도 있습니다 ...). 따라서 프로그래머의 겸손한 요청 일뿐입니다. "제발, 내 말을 들으시겠습니까?" "내가 말한대로 지금 실행하라!"라는 명령이 아닙니다. 언어 단어를 사용하여 죄송하지만 JVM의 GC 작동 방식을 정확하게 알려줍니다.
Roland

10

finalize()리소스 누수를 포착하는 데 유용 할 수 있습니다. 리소스를 닫아야하지만 로그 파일로 닫히지 않았다는 사실을 기록하지 않은 경우 리소스를 닫습니다. 이렇게하면 리소스 누수를 제거하고 문제가 발생했음을 알 수 있으므로 해결할 수 있습니다.

1.0 alpha 3 (1995) 이후 Java로 프로그래밍 해 왔으며 아직 마무리 작업을 재정의하지 않았습니다 ...


6

리소스를 정리하기 위해 finalize ()에 의존해서는 안됩니다. finalize ()는 클래스가 가비지 수집 될 때까지 실행되지 않습니다. 리소스 사용이 끝나면 명시 적으로 리소스를 비우는 것이 훨씬 좋습니다.


5

위의 답변에서 요점을 강조하기 위해 : 파이널 라이저는 외로운 GC 스레드에서 실행됩니다. 필자는 개발자가 일부 파이널 라이저에 작은 수면을 추가하고 의도적으로 멋진 3D 데모를 무릎에 가져간 주요 Sun 데모에 대해 들었습니다.

테스트 환경 진단을 제외하고는 피하는 것이 가장 좋습니다.

Eckel 's Thinking in Java에는 이것에 대한 좋은 섹션 이 있습니다.


4

흠, 기존 풀로 반환되지 않은 개체를 정리하는 데 한 번 사용했습니다.

그들은 많이 지나갔으므로 언제 수영장으로 안전하게 돌아갈 수 있는지 알 수 없었습니다. 문제는 가비지 수집 중에 개체 풀링으로 인한 절감보다 훨씬 큰 페널티가 발생한다는 것입니다. 전체 풀을 뜯어 내고 모든 것을 역동적으로 만들고 그 작업을 완료하기 전에 약 한 달 동안 프로덕션되었습니다.


4

에서하는 일에주의하십시오 finalize(). 특히 자원을 정리하기 위해 close () 호출과 같은 용도로 사용하는 경우. 우리는 실행중인 Java 코드에 JNI 라이브러리가 연결되어있는 몇 가지 상황에 처해 있었고 finalize ()를 사용하여 JNI 메소드를 호출하는 모든 상황에서 매우 나쁜 Java 힙 손상이 발생합니다. 손상은 기본 JNI 코드 자체로 인한 것이 아니며 모든 메모리 추적이 기본 라이브러리에서 양호했습니다. 우리가 finalize ()에서 JNI 메소드를 호출한다는 것은 단지 사실이었습니다.

이것은 여전히 ​​널리 사용되는 JDK 1.5에서 이루어졌습니다.

우리는 무언가가 훨씬 나중에 잘못되었다는 것을 알지 못했지만 결국 범인은 항상 JNI 호출을 사용하는 finalize () 메소드였습니다.


3

자원을 확보하기 위해 일종의 "정리"메소드를 호출해야하는 다른 개발자가 사용할 코드를 작성할 때. 때로는 다른 개발자가 정리 (또는 닫기, 파괴 또는 기타) 메소드 호출을 잊어 버리는 경우가 있습니다. 가능한 리소스 누수를 피하기 위해 finalize 메서드를 확인하여 메서드가 호출되었는지 확인하고 그렇지 않은 경우 직접 호출 할 수 있습니다.

많은 데이터베이스 드라이버는 Statement 및 Connection 구현에서이를 수행하여 밀접하게 호출하는 것을 잊어 버린 개발자에 대해 약간의 안전을 제공합니다.


2

편집 : 좋아, 그것은 실제로 작동하지 않습니다. 나는 그것을 구현하고 때로는 실패하면 괜찮다고 생각했지만 finalize 메소드를 한 번만 호출하지도 않았다.

나는 전문 프로그래머는 아니지만 내 프로그램에서는 finalize ()를 사용하는 좋은 경우의 예라고 생각하는 경우가 있습니다. 즉, 내용이 파괴되기 전에 디스크에 내용을 쓰는 캐시입니다. 매번 파괴 될 때마다 실행될 필요는 없으므로 프로그램 속도가 빨라지기 때문에 잘못하지 않았기를 바랍니다.

@Override
public void finalize()
{
    try {saveCache();} catch (Exception e)  {e.printStackTrace();}
}

public void saveCache() throws FileNotFoundException, IOException
{
    ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("temp/cache.tmp"));
    out.writeObject(cache);
}

캐시 (디스크로 플러시 할 유형)가 좋은 예라고 생각합니다. 그리고 마무리가 불려지더라도 땀이 나지 않습니다.
foo

2

전역 / 정적 장소에 추가 된 (필요하지 않은) 항목을 제거하는 것이 편리하며 개체를 제거 할 때 제거해야합니다. 예를 들어 :

    private void addGlobalClickListener () {
        weakAwtEventListener = 새로운 WeakAWTEventListener (this);

        Toolkit.getDefaultToolkit (). addAWTEventListener (weakAwtEventListener, AWTEvent.MOUSE_EVENT_MASK);
    }

    @우세하다
    protected void finalize ()에서 Throwable {
        super.finalize ();

        if (weakAwtEventListener! = null) {
            Toolkit.getDefaultToolkit (). removeAWTEventListener (weakAwtEventListener);
        }
    }

리스너가 this생성자에서 전달 된 인스턴스에 대한 강력한 참조를 가질 때 해당 인스턴스에 도달 할 수 없게되므로 finalize()어쨌든 정리되지 않습니다. 반면에 리스너가 이름에서 알 수 있듯이 해당 객체에 대한 약한 참조를 유지하는 경우이 구성은 정리하지 않아야 할 때 정리 될 위험이 있습니다. 객체 수명주기는 애플리케이션 시맨틱을 구현하기위한 올바른 도구가 아닙니다.
Holger

0

iirc-고가의 리소스에 대한 풀링 메커니즘을 구현하는 수단으로 finalize 메서드를 사용할 수 있으므로 GC도 얻지 못합니다.


0

참고로 :

finalize ()를 재정의하는 객체는 가비지 수집기에서 특별히 처리합니다. 일반적으로 개체가 더 이상 범위 내에 있지 않으면 수집주기 동안 개체가 즉시 소멸됩니다. 그러나 최종화 가능한 객체는 대신 대기열로 이동합니다. 여기서 별도의 마무리 스레드가 대기열을 비우고 각 객체에서 finalize () 메서드를 실행합니다. finalize () 메소드가 종료되면 다음 사이클에서 객체는 가비지 수집 준비가됩니다.

출처 : finalize ()는 Java-9에서 더 이상 사용되지 않습니다.


0

리소스 (파일, 소켓, 스트림 등)는 일단 완료되면 닫아야합니다. 그들은 일반적으로 close()우리가 일반적으로 진술 finally섹션 에서 호출하는 방법을 가지고 있습니다 try-catch. finalize()최종 개발자가 항상 호출 될 것이라는 보장이 없기 때문에 가끔은 소수의 개발자가 사용할 수도 있지만 IMO는 적합하지 않습니다.

Java 7에는 다음 과 같이 사용할 수있는 try-with-resources 문이 있습니다.

try (BufferedReader br = new BufferedReader(new FileReader(path))) {
  // Processing and other logic here.
} catch (Exception e) {
  // log exception
} finally {
  // Just in case we need to do some stuff here.
}

위의 예제에서 try-with-resource는 메소드 BufferedReader를 호출 하여 자원 을 자동으로 닫습니다 close(). 원하는 경우 자체 클래스에서 Closeable 을 구현 하고 비슷한 방식으로 사용할 수 있습니다. IMO 더 깔끔하고 이해하기 쉬운 것 같습니다.


0

개인적으로, 나는 finalize()한 가지 희귀 한 상황을 제외하고는 거의 사용하지 않았습니다 . 사용자 정의 제네릭 형식 컬렉션을 만들고 finalize()다음을 수행 하는 사용자 지정 방법을 작성했습니다 .

public void finalize() throws Throwable {
    super.finalize();
    if (destructiveFinalize) {
        T item;
        for (int i = 0, l = length(); i < l; i++) {
            item = get(i);
            if (item == null) {
                continue;
            }
            if (item instanceof Window) {
                ((Window) get(i)).dispose();
            }
            if (item instanceof CompleteObject) {
                ((CompleteObject) get(i)).finalize();
            }
            set(i, null);
        }
    }
}

( CompleteObject당신은 당신이 거의 구현하지 구현 한 것을 지정할 수 있습니다 내가 만든 인터페이스입니다 Object방법처럼은 #finalize(), #hashCode()#clone())

따라서 자매 #setDestructivelyFinalizes(boolean)방법을 사용하면 내 컬렉션을 사용하는 프로그램은이 컬렉션에 대한 참조를 삭제하면 내용에 대한 참조도 삭제되고 JVM을 의도하지 않게 유지하는 모든 창을 폐기 할 수 있습니다. 나는 또한 스레드를 멈추는 것을 고려했지만 완전히 새로운 웜 캔을 열었습니다.


4
호출 finalize()당신에 CompleteObject위의 코드에서처럼 인스턴스은 JVM이 여전히 호출 하듯이, 두 번 전화를받을 수 있음을 의미한다 finalize()이러한 개체가 실제로 도달 된 후 어떤 때문에 마무리의 논리로, 수도, 전에finalize() 당신의 특별 징수의 방법 동시에 전화를 받거나 동시에 전화를받습니다. 나는 당신의 방법에서 스레드 안전을 보장하기위한 어떤 조치도 보지 못하므로, 당신은 이것을 알지 못하는 것 같습니다…
Holger

0

수락 된 답변은 마무리하는 동안 리소스를 닫을 수 있음을 나타냅니다.

그러나이 답변 은 적어도 JIT 컴파일러가있는 java8에서는 예기치 않은 문제가 발생하여 객체가 유지 관리하는 스트림에서 읽기를 마치기 전에도 최종자가 호출되는 경우가 있습니다.

따라서 그러한 상황에서도 finalize를 호출하는 것은 권장 되지 않습니다 .


임의의 스레드에 의해 종료자가 호출 될 수 있으므로 작업이 스레드 안전으로 설정되는 경우 작동합니다. 올바르게 구현 된 스레드 안전성은 닫기 조작뿐만 아니라 자원을 사용하는 조작이 동일한 오브젝트 또는 잠금에서 동기화되어야 함을 나타내므로 사용과 닫기 조작 사이에 이전에 관계가 발생하여 너무 빨리 막을 수 없습니다. 마무리. 그러나 물론 전체 사용량에 대해 높은 가격에…
Holger
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.