【问题标题】:How to clear collections in javafx.scene.Scene$MouseHandler?如何清除 javafx.scene.Scene$MouseHandler 中的集合?
【发布时间】:2019-05-07 11:26:53
【问题描述】:

我有 2 个Pane。第一个窗格是主菜单,其children 中只有Rectangle。第二个窗格是我的游戏。当我进入主菜单时,我使用以下方法清除游戏窗格

//Fighting fighting = new Fighting();
//There is Pane fighting in fighting
if(fighting != null) {
    fighting.getFighting().getChildren().clear();
    fighting = null;
    System.gc();
}

当我scene.setRoot(fighting.getFighting()); 并且什么都不做时(不要将鼠标悬停在具有OnMouse...() 的对象上,不要调用移动播放器的方法)并退出到主菜单(通过单击 Esc)

scene.setOnKeyPressed(event -> {
    if (event.getCode()==KeyCode.ENTER) setFighting();
    if (event.getCode()==KeyCode.ESCAPE) setMainMenu();
});

在这种情况下,内存没有问题,GC 会删除无用的对象。

但是如果我单击/悬停在任何带有listeners 的对象上或在播放器上调用move(),GC 不会删除相同的对象。如果我重新进入游戏窗格并使用通常,GC 会从前一个会话中删除对象,并且不会从当前会话中删除它们

在我的分析器中,我发现对这些无用对象的引用存储在Pane 中,它位于Scene 的匿名类MouseHandler 中的ArrayList 之一中。无法添加imagegood。

我还发现堆中只有 2 个Pane。其中之一是mainMenu。我理解它是因为它的children 中只有Rectangle。第二个窗格的子级等于children.size() == 0

代码来自Scene & MouseHandler

private MouseHandler mouseHandler;

class MouseHandler {

   /* lists needed for enter/exit events generation */
    private final List<EventTarget> pdrEventTargets = new ArrayList<EventTarget>();
    private final List<EventTarget> currentEventTargets = new ArrayList<EventTarget>();
    private final List<EventTarget> newEventTargets = new ArrayList<EventTarget>();

    private final List<EventTarget> fullPDRCurrentEventTargets = new ArrayList<EventTarget>();
    private final List<EventTarget> fullPDRNewEventTargets = new ArrayList<EventTarget>();
    private EventTarget fullPDRCurrentTarget = null;

}

是否可以清除这些集合或修复内存泄漏?谢谢解答

【问题讨论】:

    标签: java javafx mouseevent listener


    【解决方案1】:

    从技术上讲,您可以使用 Reflection API 访问该列表并手动清除它,但我不确定这样做是否安全。

    AFAIK pdrEventTargets 列表包含组件链,该组件链表示从场景到最后一次单击的组件的路径,并且每次单击都会刷新该列表。因此,如果您在替换了组件树的一个分支并且仍然在该列表中看到一堆关于已删除组件的引用的情况下,这些将在 MouseHandler 的下一次单击处理时从 pdrEventTargets 中删除。至少当我在 jdk 1.8 调试时它的行为完全一样。可能你有完全相同的行为,所以没有理由担心,至少如果这些过时的组件不持有对某些“重”对象的引用,这些对象在这些组件被删除后不应该存在。在这种情况下,您应该在组件移除过程中移除该引用。

    【讨论】:

    • 非常好的答案,如果窗格携带大量数据,在我的情况下是千兆字节,并且没有来自用户的交互,溢出非常接近,所以反射是唯一的解决方法。虽然从托管视图中删除资源后不立即释放资源的行为确实很奇怪。
    猜你喜欢
    • 2012-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-04
    • 2015-06-06
    相关资源
    最近更新 更多