JavaFX GUI doesn't release memory

2019-07-23 14:04发布

I've been struggling for weeks to resolve the memory leaks within our JavaFX application, and thought today I was at a complete loss with it so decided to write the simplest application application I could think of to prove JavaFX could in fact release memory and therefore proving I was doing something wrong. To my surprise this seems to leak memory too.

Can anyone advise why the following application still has a javafx.scene.control.Label in the heap after the button is clicked? The way I checked it was there was with jprofiler.

public class MemoryTestApplication extends Application {

    @Override
    public void start(Stage primaryStage) {
        //root pane
        final VBox root = new VBox();

        //label to remove when button is clicked
        final Label label = new Label("Remove Me");
        root.getChildren().add(label);

        //button to remove label
        Button btn = new Button("Remove label");
        btn.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                root.getChildren().remove(label);
            }
        });
        root.getChildren().add(btn);

        //create scene and stage
        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

1条回答
爷、活的狠高调
2楼-- · 2019-07-23 14:46

Your anonymous inner class for the event handler is holding a reference to the label, and your button is holding a reference to the event handler.

The anonymous inner class is going to have two synthetically generated fields, created by the compiler, like:

final Label val$label;
final MemoryTestApplication this$0;

Since these are final, you can't clear label after using it by label = null;, so I think your best bet is to change the event handler to a normal, named class, pass the label reference in to its constructor, and then clear it after using it to remove the label from the layout. (You would want to test that it was not null before removing, so that it would only be removed the first time the button is pressed).

查看更多
登录 后发表回答