มีวิธีที่ปลอดภัยที่จะใช้เครื่องมือทำความสะอาดเพื่อ unregister เป็นผู้ฟังที่?

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

ปัญหาคือตอนนี้วัตถุที่ไม่เคยกลายเป็นท่อนอ็อ reachable เพราะ:

  • Cleaner ตัวมันเองถือเป็นแข็งแกร่งอ้างอิงไป cleanupLogic
  • cleanupLogic ถือเป็นการอ้างอิงไป listener เพื่อที่จะเอาเป็นนักฟังที่
  • listener ถือเป็นการอ้างอิงไปที่ชั้นเรียนการกระทำเพื่อที่จะเรียก updateEnabled มัน
  • กการเรียนถือเป็นการอ้างอิงไป FinalizeGuardian ดังนั้นมันไม่ได้สะสม prematurely

เพราะว่า FinalizeGuardian ตัวมันเองไม่เคยกลายเป็นท่อนอ็อ reachable ที่เครื่องมือทำความสะอาดไม่เคยโทรมา

ดังนั้นสิ่งที่ฉันอยากจะรู้คือมันมีหนทางที่จะ restructure นี่เพื่อตามกฏต้องการที่จะทำให้ Cleaner ทำงานอย่างถูกต้องที่ ไม่ เกี่ยวข้องกัทำ encapsulation โดยการย้ายที่เป็นนักฟังที่ต้องออกการกระทำของผมห้องเรียนด้วยได้ไม๊?

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

คำตอบที่ดีที่สุด

3

ตราบใดที่ FlavorListener นั่นจดทะเบียนในชื่อของที่เป็นที่มาของเหตุการณ์มันจะไม่มีวันกลายเป็นไม่ค่อยเป็นมิต(ตราบใดที่คนที่มาของเหตุการณ์ยังคง reachable). นี่ implies ว่า PasteAction ตัวอย่างซึ่งเป็นนักฟังที่ปรับปรุงจะยังไม่เคยกลายเป็นไม่ค่อยเป็นมิตเหมือนอย่างที่เป็นนักฟังที่มีแข็งแกร่งอ้างอิงกับมัน

ทางเดียวที่จะ decouple พวกเขา reachability คือต้องเปลี่ยนเป็นนักฟังที่ที่เดียวที่รักษาความอ่อนแออ้างอิงถึงเพื่อวัตถุที่มันรายงานแล้ว ข้อตอนที่คุณกำลังใช้ 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 ได้ referent เป็ Objectอย่างที่ทำความสะอาการกระทำจะต้องไม่เข้าไปสมาชิกของการกระทำแต่ได้รับความจำเป็นค่าของที่แยกออกค่าพารามิเตอร์.

แต่หลังจากที่แสดงว่าเป็นเครื่องมือทำความสะอาดใช้งานอาจจะดูเหมือนฉันต้อย่าพูดแบบนี้เลยแต่เขาอาจช่วยเราจากใช้กลไกของมันโดยเฉพาะอย่างยิ่งเป็นคนเดียวที่ทำความสะอาดกลไกของมัน. นี่มันไม่ได้เป็นเพียงส่งผลกระทบต่อความทรงจำ consumption แต่เป็น พฤติกรรม ของโปรแกรมเพราะตราบเท่าที่คนจะอ้างอิงไปยังไม่ได้ถูกลบออกที่เป็นนักฟังที่จะทำให้ได้รับแจ้งและให้กำลังปรับปรุงการล้าหวัตถุ.

ตั้งแต่กองขยะไปได้.ออกนักสะสมเพียงกระตุ้นโดยความทรงจำต้องการมันจึงเป็นไปได้ที่มันไม่หนีไปหรือไม่สนใจเรื่องพวกนี้ไม่กี่วัตถุเพราะมีเพียงพอหน่วยความจำที่เหลือในขณะที่หน่วยประมวลผลอยู่ภายใต้ตัวหนักโหลดเพราะของหลายของล้าห listeners ถึงเราจะไม่ได้รางวัลเราก็สนุกที่จะปรับปรุงล้าหวัตถุ(ฉันเคยเห็นเรื่อยู่ในเหตุการณ์จำลองฝึกซ้อม).

เพื่อทำให้เรื่องแย่กับ concurrent ขยะพวกนักสะสมมันเป็นไปได้ว่าพวกเขาสะสมวังวนซ้ำแล้วซ้ำอี overlaps กับคนที่จริงแล้ล้าหรประหารชีวิตของ updateEnabled() กระตุ้นโดยเป็นนักฟังที่(เพราะการอ้างอิงไม่ได้เคลียร์ยัง). ซึ่งจะ actively ป้องกันกองขยะไปได้.ออกคลังภาพของพวกวัตถุงแม้ตอนที่ถังขยะนักสะสมวิ่งและก็จะไม่อย่างนั้นเก็บพวกเขา

ในที่แสนสั้นนั้นทำความสะอาดควรจะไม่เชื่อใจกองขยะไปได้.ออกนักสะสม

2021-11-26 15:49:36

ในภาษาอื่นๆ

หน้านี้อยู่ในภาษาอื่นๆ

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

ดังอยู่ในนี้หมวดหมู่

ดังคำถามอยู่ในนี้หมวดหมู่