Чрезмерное использование оперативной памяти - JavaFX - PullRequest
2 голосов
/ 15 марта 2019

При каждом изменении сцены использование памяти увеличивается, и она никогда не «очищается», если я перехожу назад и вперед через 2 экрана, то же самое происходит несколько раз, каждый раз, когда я вхожу на тот же экран, это увеличивает использование, только первый экран для второго, который мы видим, что использование уменьшается, где он отмечен на рисунке красным.

enter image description here

Обратите внимание, что сбор мусора только увеличивается:

enter image description here

Для смены сцен я использую следующий код:

public void changeStage(Parent event, String title, String url){
    Platform.runLater(() -> {
        try {
            Parent loader = FXMLLoader.load(getClass().getResource("/gro/admin/java/" + url));
            event.getScene().setRoot(loader);

        } catch (IOException ex) {
            Logger.getLogger(LoginController.class.getName()).log(Level.SEVERE, null, ex);

        } 
    });
}

После поиска я увидел, что System.gc(); может помочь, но безрезультатно. Я попытался заставить все объекты перейти в нуль и вызвать его, чтобы попытаться освободить ОЗУ, но безрезультатно:

Call changeStage(this, stackPane, "Title", "Url");, This в данном случае это сам класс, который реализует Initializable

public void changeStage(Object obj, Parent event, String title, String url){
    Platform.runLater(() -> {
        try {
            nullAll(obj, event);
            Parent loader = FXMLLoader.load(getClass().getResource("/gro/admin/java/" + url));
            event.getScene().setRoot(loader);

        } catch (IOException ex) {
            Logger.getLogger(LoginController.class.getName()).log(Level.SEVERE, null, ex);

        } 
    });
}

private static void nullAll(Object obj, Parent root){
    ObservableList<Node> nodes = getAllViews(root);
    nodes.forEach(node -> node = null);
    nodes.clear();
    nodes = null;
    if(root instanceof StackPane){
        ((StackPane) root).getChildren().clear();
        root = null;

    }else{
        root = null;

    }

    obj = null;
    System.gc();
}

private static ObservableList<Node> getAllViews(Parent root) {
    ObservableList<Node> nodes = FXCollections.observableArrayList();
    addAllDescendents(root, nodes);
    return nodes;
}

private static void addAllDescendents(Parent parent, ObservableList<Node> nodes) {
    parent.getChildrenUnmodifiable().stream().map((node) -> {
        nodes.add(node);
        return node;
    }).map((node) -> {
        if (node instanceof Parent){
            addAllDescendents((Parent) node, nodes);

        }
        return node;            
    }).map((node) -> {
        if(node instanceof ScrollPane){
            addAllDescendents((Parent) ((ScrollPane) node).getContent(), nodes);
            nodes.add(((ScrollPane) node).getContent());
        }
        return node;            
    }).map((node) -> {
        if(node instanceof TabPane){
            ((TabPane) node).getTabs().forEach((t) -> {
                addAllDescendents((Parent) ((Tab) t).getContent(), nodes);
            });
        }
        return node;
    }).filter((node) -> (node instanceof JFXTabPane)).forEachOrdered((node) -> {
        ((JFXTabPane) node).getTabs().forEach((t) -> {
            addAllDescendents((Parent) ((Tab) t).getContent(), nodes);
        });
    });
}

Это не повлияло ни на что в памяти, оно только сделало обмен сценами "захлебнувшимися" и немного больше.

Кто-нибудь знает, как я могу на самом деле изменить сцену без этой ненужной "кучи"?

Редактировать: Ах, еще один интересный момент, это использование памяти в процессе использования идет от 1 ГБ легко, но если я использую какую-то программу очистки оперативной памяти, она идет ниже 100 МБ.

До:

enter image description here

После того, как:

enter image description here

1 Ответ

0 голосов
/ 15 марта 2019

Короче говоря: речь идет не о вашем коде, а о том, как работает Java. В общем случае JavaFX требуется больше памяти, он потребляет больше памяти, чем необходимо. По умолчанию Java не возвращает память обратно в вашу систему, даже если вы запускаете сборку мусора, поэтому если программе JavaFX требуется много памяти для обработки, но она освобождается после этого JRE продолжает удерживать максимальный уровень памяти навсегда, и сборщик мусора будет запускаться реже, потому что есть так много свободной неиспользуемой памяти, тем не менее, вы можете изменить поведение JVM, как выделяется память, как это освобожден и при запуске ГХ, см. Руководство по настройке производительности

...