RAM过多支出-JavaFX

时间:2019-03-15 13:55:13

标签: java performance javafx javafx-8

每次场景更改时,内存的使用都会增加,并且永远不会被“清理”,如果我在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();可以帮助但没有效果。 我试图使所有对象变为null并调用它以尝试释放RAM,但没有效果:

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

这不会影响内存中的任何内容,只会使场景交换“阻塞”甚至更多。

有人知道我在没有这种不必要的“堆放”的情况下实际上可以怎么做吗?

编辑:嗯,另一个有趣的地方是,在使用过程中这种内存的使用从1gb开始很容易,但是如果我使用某些ram清理程序,它的内存将低于100mb。

之前:

enter image description here

之后:

enter image description here

1 个答案:

答案 0 :(得分:-1)

悠久的历史:与您的代码无关,与Java的工作原理有关。 JavaFX通常需要更多的内存,它将消耗更多的内存,因为默认情况下,即使触发垃圾回收,Java也不会将内存返回给您的系统,因此,如果JavaFX程序需要大量内存来处理但需要释放之后,JRE会永远保持最大的内存级别,并且垃圾回收器的触发频率会降低,因为有很多可用的未使用内存,但是,您可以更改JVM行为,内存分配方式,内存分配方式已释放并且触发GC时,请参见Performance Tuning Guide

相关问题