Как очистить коллекции в javafx.scene.Scene $ MouseHandler? - PullRequest
0 голосов
/ 05 декабря 2018

У меня есть 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, который находится в одном из ArrayList в анонимномкласс MouseHandler в Scene.Не могу добавить image хорошо.

Также я обнаружил, что в куче всего 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;

}

Можно ли очистить эти коллекции или устранить утечку памяти?Спасибо за ответы

1 Ответ

0 голосов
/ 27 января 2019

Технически, вы можете использовать Reflection API , чтобы получить доступ к этому списку и очистить его вручную, но я не уверен, что это будет безопасно.

AFAIK, что список pdrEventTargets содержит цепочку компонентов, которая представляет путь от сцены к компоненту, который был нажат последним, и этот список обновляется при каждом щелчке.Так что если вы находитесь в ситуации, когда вы заменили ветку дерева компонентов и все еще видите кучу ссылок на удаленные компоненты в этом списке, они будут удалены из pdrEventTargets при обработке следующего клика на MouseHandler.По крайней мере, он ведет себя именно так, пока я отлаживаю на jdk 1.8.Вероятно, у вас точно такое же поведение, поэтому не должно быть причин для беспокойства, по крайней мере, если эти устаревшие компоненты не содержат ссылок на некоторые «тяжелые» объекты, которые не должны жить после удаления этих компонентов.В этом случае вы должны удалить эти ссылки как часть процесса удаления компонентов.

...