문제

나는 독서를 통해 많은 신인에 대한 질문에 자바 finalize() 고 그것을 찾을 종류의 어리둥절하게는 아무도 정말 하는 마무리()은 신뢰할 수 없는 방법을 깨끗한 리소스입니다.사람을 보았는 의견들은 그것을 사용하여 깨끗한 연결이 정말 무서운 이후 할 수있는 유일한 방법은 가깝게 보증하는 연결을 닫을 구현하도(잡기)마지막으로.

지 않았습 교육 CS,하지만 나는 자바 프로그래밍을 전문적으로 십 년 가까이 이제 나는 본 적이 없는 누군가를 구현하 finalize() 에서 생산 시스템니다.이것은 여전히는 것을 의미하지 않는 그것을 가지고 있지 않을 사용하거나는 사람들과 함께 일했을하고있다.

그래서 제 질문은 무엇을 사용하는 경우가 있을 구현하기 위한 finalize() 처리할 수 없는 더 많은 신뢰를 통해 다른 프로세스 또는 구문에서 언어?

제공해 주십시오 특정 시나리오 또는 당신의 경험을 단순히 반복하 Java,문서 또는 마무리의 의도를 사용하지 않으로 충분히지 않는 질문입니다.

도움이 되었습니까?

해결책

당신은 그것을 사용할 수 있으로 백업을 위한 물체를 들고 외부자원(소켓에,파일,etc.).구현 close() 방법하고는 문서를 호출됩니다.

구현 finalize()close() 처리하는 경우에 당신은 그것을 감지되지 않았다.어쩌면 무언가를 덤프하기 stderr 하는 것을 지적하신 후 청소 버그가 있는 디자인을 자랑합니다.

제공하는 여분의 안전에서는 뛰어난/버그가 있는 상황이다.모든 발신자가 할 올바른 try {} finally {} 재료니다.불행한 일이지만,대부분에서 환경입니다.

나는 것에 동의하는것은 거의 필요하지 않습니다.과 코멘트 포인트,그것은 함께 제공됩 GC 오버헤드가 발생합니다.만 사용해야 하는 경우에는"벨트와 멜빵"안전에서는 오래 실행되는 앱입니다.

내가 참으로 자바의 9, Object.finalize() 은 사용되지 않!그들이 지점을 java.lang.ref.Cleanerjava.lang.ref.PhantomReference 으로 대안입니다.

다른 팁

finalize() 힌트를 JVM 는 것이 좋은 코드를 실행에 지정되지 않은 시간입니다.이것은 좋을 때 당신이 원하는 코드를 갑 실패할 수도 있습니다.

아무것도 하에서 중요한 종료자(기본적으로 아무것도를 제외하고 기록)은 또한에서 좋은 세 가지 상황:

  • 도박을 하려고 하는 다른 확정 개체 여전히 상태에서는 프로그램의 나머지는 고려 유효합니다.
  • 을 추가하려는 많은 검사 코드가 모든 방법들을 통해 모든 당신의 클래스는 종료자,그들은 확인 후 제대로 동작하는 종료.
  • 당신이 원하는 실수로 부활을 확정체,그리고 많은 시간을 보내는 이유를 알아 내기 위해 노력하고있 그들은 작동하지 않는,및/또는 왜 그렇지 않을 얻을 완료 할 때 그들은 결국 발표했다.

가 필요하다고 생각되는 경우를 마무리(),때로는 당신이 정말로 원하는 것입니다 팬텀 참조 (는 예제에서는 주어진을 확보할 수 있습니다 열심히 참조하여 연결해 사용하는 그것의 referand,그리고 그것을 닫은 후에 팬텀 참조되었 대기).이 또한 속성이 있는 신비의 실행되지 않지만 적어도 그것은할 수 있는지에 대한 메소드를 호출하거나 부활을 확정 개체입니다.그래서 그냥 오른쪽 상황에 대한 곳에서 당신이 절대적으로 필요를 닫는 연결을 깨끗하게,하지만 당신은 매우 좋아하고 클래스의 클라이언트가할 수 없거나지 않을 것이 전화를 스스로를 닫습니다(실제로 공정한 충분의 요점은 무엇을 갖는 쓰레기 수집가는 모든 경우에 인터페이스 디자인 특정 작업을 찍은 이전 컬렉션?그냥 우리를 다시 넣에서의 일 malloc/무료입니다.)

다른 시간에 당신에 필요한 자원을 생각하는 당신은 수의 관리 더 강력합니다.예를 들어,당신은 왜 필요를 닫는 연결?그것을 기반으로 해야 합 어떤 종류의 I/O 시스템에서 제공(socket,파일,무엇이건),그래서할 수 없는 이유는 당신 시스템에 의존하여 가까운 당신을 위해 그것을 할 때 가장 낮은 수준의 자원이 글로벌시민교?서버인 경우 다른 쪽 끝에서 절대적으로 필요 당신을 연결을 닫을 깨끗하게 오히려 다만 떨어지는 소켓을,그 다음에 무슨 일이 일어날 때 누군가가 여행을 통해 전력 케이블계의의 코드를 실행하기에,또는 중간 네트워크가?

면책 조항:일했에서 JVM 을 구현니다.I hate 종료자.

간단한 규칙사용 종료자.

사실 혼자 하는 객체에 종료자(에 관계없이 무엇 코드를 실행하는)일으킬 정도는 상당한 오버헤드를 쓰레기 모음.

문서 브라이언 Goetz:

체 종료자(는 사람들 가 아닌 사소한 마무리를()method) 중요한 오버헤드 비교기 체없이 종료자,그리고야 용을 절약해줍니다.Finalizeable 체가 모두 느리게 할당 고 느리게 수집합니다.에 할당 시간 JVM 등록해야합니다 어떤 finalizeable 체 쓰레기 수집하고,(적어도서 핫스팟 JVM 구현) finalizeable 체를 따라야합니다 느린 할당 경로를 다른 대부분의 체입니다.마찬가지로,finalizeable 체는 느리게 수집,too.그 적어도 두 가비지 컬렉션 사이클(에서 최고의 경우)기 finalizeable 개체 회수할 수 있습, 고 쓰레기를 수집 할 수 있다 추가 작업을 호출하여 종결입니다.결과 더 많은 시간을 보냈 및 할당 개체를 수집하고 더 많은 압력에 쓰레기통 수집기 때문에,메모리에 의해 사용 도달할 수 없는 개체 finalizeable 더 길게 유지.결합하는 것으로 는 사실을 종료자하지 않은 상에서 실행하는 모든 예측 가능 시간 내,또는에서 모든 수 볼 수 있다는 것은 상대적으로 적 는 상황이 종료 오른쪽에 도구를 사용하실 수 있습니다.

시간 사용을 마무리 생산에 있는 코드를 구현하는지 확인한 주체의 자원 정리했다,그리고 그렇지 않다면,로그는 매우 음성 메시지입니다.지 않은 실제로 시도하고 그것을 자체,그것은 단지 외쳤다 많이지 않으면 제대로 이루어집니다.로 밝혀졌다 매우 유용합니다.

I've been doing Java 전문적으로 1998 년 이후로,그리고 나는 결코 구현 finalize().지 않는다.

나는 확실하지 않습니다,하지만...

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

그래서 나는 태양을 발견 는 경우(그들은 생각한다)그것을 사용해야 합니다.

수락 응답이 좋은,나를 추가하는 방법의 기능을 마무리지 않고 사용합니다.

보""를 참조하는 클래스입니다.약한 참조 팬텀 참조&소프트 참조.

당신을 유지하기 위해 사용할 수 있습이 참조하는 모든 개체이지만,이에 참조 혼자서 멈추지 않을 것입니다 GC.깔끔한 것을 알 수 있습니다 당신은 그것을 메소드를 호출 될 때,삭제할 수 있습니다이 방법이 될 가 호출됩니다.

으로 마무리:나는 사용을 마무리 한 번 이해하는 어떤 물체되고 있었다 해제됩니다.당신은 일부를 재생할 수 있습니 깔끔한 게임으로 정적,참조 계산은-하지만 그것은 단지에 대한 분석,하지만 조심한다(다만에 완료,하지만 당신은 가능성이 가장 높은 그것을 참조):

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

그것은 누군가가지 않았다 그들이 무엇을 해야 하는지 알게 되었습니다."청소"이 같은 사실상 필요하지 않습니다.할 때 클래스 GC 것,이것은 자동으로 수행됩니다.

당신이 찾아 같은 코드에서는 마무리 그것은 자주 묻는 질문에 대한 답변을 볼 사람이 그것을 썼는 혼란스러워 했다.

는 경우 다른 곳에서,그것은 될 수 있는 코드가 유효한 패치를 나쁜 모델(클래스를 유해 오랜 시간이 어떤 이유로 일들이 그것을 참조를 수동으로 해제되기 전에 객체가 GC 고).일반적으로 그것 때문에 사람을 잊을 수신기를 제거하거나 무언가를 알아낼 수 없습니다 왜 그들의 개체고 있지 않은지 GC 거래서 그들은 그 물건을 삭제하는것을 말하고 그들의 어깨를 으쓱하고보실 수 있습니다.

그것은 결코 사용되어야 하지 않을 청소하는 것이"빨리".

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() 유용할 수 있습 catch 자원 발전하고 있습니다.면 자원을 닫아야만 쓰다는 사실이 닫히지 않았을 로그 파일을 닫습니다.는 방법을 제거하면 리소스 누출고 자신에게는 방법을 알고있는 그것이 일어났다 그래서 당신은 그것을 해결할 수 있습니다.

나 자바 프로그래밍부터 1.0 알파 3(1995 년)그리고 나는 아직을 재정의 완료를 위해 아무것도...

당신 없에 따라 완료를()을 정리하는 리소스에 대한 당신.을 마무리()지 않을 때까지 실행 클래스가 쓰레기 수집하는 경우,다음입니다.그것은 훨씬 더 나은 명시적으로 자유로운 자원을 때 당신을 사용하여 수행됩니다.

을 강조하는 시점에서 위의 답변:종료자에서 실행됩 론 GC thread.내가 들어 있는 주요 태양 데모는 개발자는 실내 수영장,야외 수영장,사우나 잠을 몇 가지 종료자적으로 의도적으로 가져온 그렇지 않으면 멋진 3D 데모를 무릎.

을 피하기 위해 최선을과 함께,가능한 예외의 테스트-환경 진단을 수행합니다.

Eckel 의 생각에는 자바 좋은 섹션 니다.

Hmmm,I 한번 사용하면 그것은 정체되지 않는 반환되는 기존 수영장도 있습니다.

그들이 주위에 전달을 많이,그래서 그것은 말할 수 없을 때 수 있는 안전하게 반환될 수 있습니다.문제는 그것은 도입하는 거대한 처벌하는 동안 가비지 컬렉션에는 훨씬 더 큰 어떤 것보다 저축에서 풀링니다.그 생산에서 약 한 달 전에 내가 찢어진 모든 수영장,모든 것 동으로 이루어졌습니다.

조심해야에 대해 무엇을 할 finalize().특히 사용하는 경우에는 그와 같은 것들에 대한 close()를 호출하 자원을 활용하도록 하기 위해 청소.우리는 실로 여러 가지 상황을 우리가 JNI 라이브러리에 연결되어를 실행하 java 코드,그리고 어떤 상황에서 우리가 사용되는 마무리()를 호출 JNI 방법을 우리는 아주 나쁜 java 힙 손상입니다.손상에 의해 발생되지 않았는 기본 JNI 코드,모든 메모리의 흔적은 잘했어 라이브러리입니다.그것이었다는 사실 우리가 부르 JNI 방법에서 마무리()다.

이와 함께 JDK1.5 는 여전히 널리 사용.

우리는 없을 것을 찾아 나는 뭔가 잘못되었을 때까지 많은 나중에 하지만 결국에서 범인이 항상 완료()메서드를 사용하의 JNI 를 호출합니다.

할 때 쓰는 코드에 의해 사용됩니다 다른 개발자들이 필요로하는 어떤 종류의"정리"메소드 호출할을 무료로 리소스입니다.때로는 그는 다른 개발자를 호출하는 것을 잊지 마십시오 귀하의 정리(또는 가까운,을 파괴하거나,또는 어떤)방법입니다.가능성을 피하기 위해 자원의 누수를 확인할 수 있습에서 마무리 방법을 확인하는 방법이었고 그것이 아니었다면 당신을 호출 할 수 있습니다.

많은 데이터베이스 드라이버지는 이들의 성명과 연결 구현을 제공하는 작은 안전에 대한 개발자를 호출하는 것을 잊지 마십시오 닫습니다.

편집:좋아요,그것이 정말로 작동하지 않습니다.내가 구현한다고 생각하면 그것은 실패하는 경우 그에 대한 확인을 하지 않았어도 통화를 마무리 방법이 하나의 시간입니다.

나는 전문 프로그래머지만 내 프로그램이 있는 경우를 생각하는 예제의 좋은 사용하는 경우 마무리(),는 캐쉬를 쓰는 그 내용을 디스크기 전에 파괴되었다.그것은 필요가 없기 때문에 그것이 실행되는 모든 시간에 파괴,그것은 속도를 내 프로그램,내가지는 것을 희망하지 않았어요 그것은 잘못입니다.

@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);
}

그것이 편리할 수 있을 제거하는 것에 추가되어 있는 글로벌/정체되는 장소(의 필요),및 제거해야 할 경우 객체를 제거한다.예를 들어:

    private void addGlobalClickListener() {
        weakAwtEventListener = new WeakAWTEventListener(this);

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

    @Override
    protected void finalize() throws Throwable {
        super.finalize();

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

iirc-를 사용할 수 있습을 마무리 방법의 수단으로 구현하는 풀링을 위한 메커니즘 비싼 리소스-지 않도록 열심히 하고 싶습니다 너무입니다.

측면으로 주의:

는 개체를 재정의 완료를()에 의해 특별히 취급 쓰레기 수집기.일반적으로,개체를 즉시 파괴되는 동안 수집 주기 후체는 더 이상 범위에서.그러나 종료할 수 있는 객체를 대신 이동을 큐에는 별도의 스레드가 종료됩 배출 큐와 실행을 마무리()메소드 각각에 개체입니다.후에 마무리()메소드가 종료되며,개체에 마지막을 위해 준비가 될 가비지 컬렉션에서 다음의 주기입니다.

출처: 을 마무리()사용에 java-9

자원(파일 소켓 스트림 등입니다.) 닫아야 하는 일단 우리가 수행됩니다.그들은 일반적으로 close() 는 방법을 우리는 일반적으로 호출에 finally 섹션 try-catch 문입니다.때때로 finalize() 도 사용할 수 있습니다 몇 개발자만 IMO 지 않는 적절한 방법으로 보장은 없는 마무리 될 것이라고 항상.

Java7 우리가 가지고 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.
}

위의 예제에서도와-자원이 자동으로 닫 자원 BufferedReader 를 호출하여 close() 방법입니다.우리가 원하는 경우 우리를 구현할 수도 있습니다 닫기 가능 에서 우리 자신의 클래스고에서 사용하도 비슷한 방식으로 이루어집니다.IMO 그것은 더욱 깔끔하고 간단하게 이해합니다.

개인적으로,나는 거의 사용되지 않는 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 살아 실수로.고려도 중 어떤 쓰레드,하지만 개방하기로 수 있습니다.

용 대답 목록 닫기 자원 동안 마무리 할 수 있습니다.

그러나 이 답변 는 것을 보여줍에서 적어도 java8 와 JIT 컴파일러를 실행으로 예상치 못한 문제는 때때로 종료자라고도 전에 마무리 읽고 스트림에서 유지하여 귀하의 개체입니다.

그래서 그 상황에서 호출하는 것을 마무리 할 권장합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top