가 있는 안전한 방법을 사용 청소기 등록 취소할 수 있습니다.

0

질문

나는 스윙 액션스 클래스는 다음과 같습니다.

package org.trypticon.hex.gui.datatransfer;

import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.FlavorListener;
import java.awt.event.ActionEvent;
import javax.annotation.Nonnull;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.TransferHandler;

import org.trypticon.hex.gui.Resources;
import org.trypticon.hex.gui.util.FinalizeGuardian;
import org.trypticon.hex.gui.util.FocusedComponentAction;

public class PasteAction extends FocusedComponentAction {
    private final FlavorListener listener = (event) -> {
        // this method in the superclass calls back `shouldBeEnabled`
        updateEnabled();
    };

    @SuppressWarnings({"UnusedDeclaration"})
    private final Object finalizeGuardian = new FinalizeGuardian(() -> {
        Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
        clipboard.removeFlavorListener(listener);
    });

    public PasteAction() {
        Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
        clipboard.addFlavorListener(listener);
    }

    @Override
    protected boolean shouldBeEnabled(@Nonnull JComponent focusOwner) {
        TransferHandler transferHandler = focusOwner.getTransferHandler();
        if (transferHandler == null) {
            return false;
        }

        Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
        DataFlavor[] flavorsInClipboard = clipboard.getAvailableDataFlavors();
        return transferHandler.canImport(focusOwner, flavorsInClipboard);
    }

    @Override
    protected void doAction(@Nonnull JComponent focusOwner) throws Exception {
        Action action = TransferHandler.getPasteAction();
        action.actionPerformed(new ActionEvent(
            focusOwner, ActionEvent.ACTION_PERFORMED, (String) action.getValue(Action.NAME)));
    }
}

FinalizeGuardian 라고 여기에는 현재 사용하여 구현 finalize():

package org.trypticon.hex.gui.util;

public final class FinalizeGuardian {
    private final Runnable cleanupLogic;

    public FinalizeGuardian(Runnable cleanupLogic) {
        this.cleanupLogic = cleanupLogic;
    }

    @Override
    protected final void finalize() throws Throwable {
        try {
            cleanupLogic.run();
        } finally {
            super.finalize();
        }
    }
}

그래서,분명한 이유하고 싶을 사용하여 전환 Cleaner 니다.

첫 번째 시도했다가 다음과 같다:

package org.trypticon.hex.gui.util;

import java.lang.ref.Cleaner;

public final class FinalizeGuardian {
    private static final Cleaner cleaner = Cleaner.create();

    public FinalizeGuardian(Runnable cleanupLogic) {
        cleaner.register(this, cleanupLogic);
    }
}

문제는 지체 없이 된 팬텀 연결할 수 있기 때문에:

  • Cleaner 자체 보유한 강력한 참조 cleanupLogic
  • cleanupLogic 을 보유하고 참조 listener 을 제거하기 위해 수신기
  • listener 을 보유하고 참조하여 작업하기 위해 클래스를 통화 updateEnabled 그것에
  • 행동을 보유 하는 클래스를 참조하여 FinalizeGuardian 지 않도록을 얻을 수집한 조기에

FinalizeGuardian 자체 없이 된 팬텀이 닿을 수 있는,청소기는 없을 것이라고.

그래서 무엇을 알고 싶은 방법이 있을 재구성 이 규칙을 따르도록 만들기 위해 필요하 Cleaner 가 제대로 작동하는 를 포함 깨는 캡슐화에 의해 이동하는 수신기를 외부의 조치 등?

garbage-collection java swing
2021-11-24 01:39:09
1

최고의 응답

3

FlavorListener 에 등록된 이벤트 소스지 않습니다 연결할 수 없(만큼 이벤트 소스는 여전히 연결). 이 PasteAction 예를 들어 수신기를 업데이트 될 수 없 연결할 수 없으로 청취자에 강한 참조합니다.

는 유일한 방법을 분리하며 그들의 연결을 변경하는 것입 수신기만을 유지하 약한 개체에 대한 참조를 업데이트를 진행합니다. 참고 사용하는 경우 Cleanerfinalize()이, FinalizeGuardian 은 사용되지 않습니다.

코드는 것처럼 보

public class PasteAction extends FocusedComponentAction {

    static FlavorListener createListener(WeakReference<PasteAction> r) {
        return event -> {
            PasteAction pa = r.get();
            if(pa != null) pa.updateEnabled();
        };
    }

    private static final Cleaner CLEANER = Cleaner.create();

    static void prepareCleanup(
                       Object referent, Clipboard clipboard, FlavorListener listener) {

        CLEANER.register(referent, () -> clipboard.removeFlavorListener(listener));
    }

    public PasteAction() {
        Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
        FlavorListener listener = createListener(new WeakReference<>(this));
        clipboard.addFlavorListener(listener);
        prepareCleanup(this, clipboard, listener);
    }

…

참고는 중요한 부분이되었으로 배치 static 방법 실수로 캡처의 this reference 불가능합니다. 이러한 방법을 얻는 데 필요한 최소한의 자신의 일을, createListener 만 받 약한 참조하여 작업 prepareCleanup 면 참조로 Object으로,클리닝 작업해야에 액세스하지 않는 구성원의 행동 하지만 받을 필요한 값으로 별도의 매개 변수입니다.

하지만 보여주는 후에,어떻게 깨끗한 사용처럼 보일 수 있습니다,나는 강하게 억제하에서 이 메커니즘을 사용하여,특히으로 정리 메커니즘이 있습니다. 여기에,그것은뿐만 아니라 영향을 미치는 메모리이지만,또한 의하기 때문에,프로그램을 만큼,참조에 지워지지 않는 청취자이지 정보를 계속 업데이트 사용되지 않는 객체입니다.

이집 단에 의해 트리거 메모리 요구를 완벽하게 가능한지 않는 것을 실행하거나 걱정하지 않는 이러한 객체가 있기 때문에,메모리가 부족하면서,CPU 은 아래에 무거운 짐이기 때문에,많은 사용되지 않는 청취자는 바쁜데 오래된 개체(본 적은 연습에서 시나리오).

문제를 악화시킬 것으로,동시 쓰레기 수집가,그것도 그들의 컬렉션의 주기를 반복적으로 중복으로 실제로 사용되지 않는 실행 updateEnabled() 에 의해 트리거 리스너(기 때문에 참조되었 아직 삭제되지 않습니다). 는 것입니다 적극적으로 방지합 쓰레기의 컬렉션 이러한 객체는 경우에도,쓰레기 수집가를 실행하고 그렇지 않으면 그것들을 수집합니다.

즉,이러한 정리해야에 의존하지 않는 쓰레기 수집기.

2021-11-26 15:49:36

다른 언어로

이 페이지는 다른 언어로되어 있습니다

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................