एक सुरक्षित तरीका है का उपयोग करने के लिए क्लीनर अपंजीकृत करने के लिए एक श्रोता?

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 सही ढंग से काम है कि नहीं करता है शामिल है को तोड़ने के encapsulation के द्वारा चलती करने के लिए श्रोता के बाहर मेरी कार्रवाई वर्ग?

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

सबसे अच्छा जवाब

3

के रूप में लंबे समय के रूप में FlavorListener पर पंजीकृत है एक इवेंट स्रोत है, यह कभी नहीं हो जाएगा अगम्य (के रूप में लंबे समय के रूप में घटना स्रोत अभी भी पहुँच में है). इस का तात्पर्य है कि PasteAction उदाहरण जो श्रोता अपडेट भी हो जाते हैं कभी नहीं अगम्य, के रूप में श्रोता एक मजबूत संदर्भ के लिए ।

एक ही रास्ता करने के लिए दसगुणा अपने गम्यता बदलने के लिए है श्रोता के लिए, केवल बनाए रखने के एक कमजोर संदर्भ वस्तु के लिए यह अद्यतन । ध्यान दें कि जब आप का उपयोग कर रहे हैं Cleaner के बजाय finalize()में , 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 संदर्भ असंभव है । इन तरीकों को प्राप्त करने के लिए आवश्यक न्यूनतम उनकी नौकरी करते हैं, createListener केवल एक कमजोर के संदर्भ में कार्रवाई और prepareCleanup हो जाता है दिग्दर्शन के रूप में Objectके रूप में , सफाई कार्रवाई नहीं होना चाहिए किसी भी उपयोग के सदस्यों की कार्रवाई की है लेकिन आवश्यक प्राप्त मूल्यों के रूप में अलग-अलग मापदंडों ।

लेकिन बाद में दिखा रहा है, कैसे एक क्लीनर का उपयोग की तरह लग सकता है, मैं करने के लिए दृढ़ता से हतोत्साहित से इस प्रणाली का उपयोग, खासकर के रूप में ही सफाई व्यवस्था । यहाँ, यह न केवल प्रभावित करने वाले स्मृति की खपत है, लेकिन यह भी व्यवहार का कार्यक्रम है, क्योंकि, के रूप में लंबे समय के रूप में के संदर्भ में नहीं किया गया मंजूरी दे दी, श्रोता हो जाएगा सूचित और अद्यतन रखने के लिए एक अप्रचलित ऑब्जेक्ट है ।

के बाद से कचरा कलेक्टर है केवल ट्रिगर द्वारा स्मृति की जरूरत है, यह पूरी तरह से है संभव है कि यह नहीं करता है, चलाने के लिए या परवाह नहीं है इन के बारे में कुछ वस्तुओं है, क्योंकि वहाँ पर्याप्त मुक्त स्मृति, सीपीयू, जबकि हेवी लोड के अंतर्गत है, क्योंकि बहुत से अप्रचलित श्रोताओं व्यस्त होने के लिए अद्यतन अप्रचलित वस्तुओं (मैंने देखा है इस तरह के परिदृश्यों के अभ्यास में).

मामलों बदतर करने के लिए, के साथ समवर्ती कचरा कलेक्टरों, यह भी संभव है कि उनके संग्रह चक्र बार-बार overlaps के साथ एक वास्तव में अप्रचलित के निष्पादन updateEnabled() द्वारा ट्रिगर श्रोता (क्योंकि इस संदर्भ में साफ नहीं किया गया था अभी तक). जो सक्रिय रूप से रोकने के लिए कचरा संग्रह इन वस्तुओं, यहां तक कि जब कचरा कलेक्टर चलता है और अन्यथा उन्हें इकट्ठा.

संक्षेप में, इस तरह की सफाई पर भरोसा नहीं करना चाहिए कचरा कलेक्टर ।

2021-11-26 15:49:36

अन्य भाषाओं में

यह पृष्ठ अन्य भाषाओं में है

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................

इस श्रेणी में लोकप्रिय

लोकप्रिय सवाल इस श्रेणी में