Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optimizing memory leakage in JavaFX

Tags:

java

javafx-8

I have written a piece of code, to make letters appear and fly as I write them. The problem it consumes a lot of memory.

I already optimized it a little bit by

  • Sharing the path object and update its parameters in listeners.
  • Calling gc each time a new letter is printed

But it still uses a lot of memory, so any ideas about how to reduce its memory utilization ?

Thanks in advance.



    package sample;

    import javafx.animation.PathTransition;
    import javafx.application.Application;
    import javafx.scene.Scene;
    import javafx.scene.layout.Pane;
    import javafx.scene.paint.Color;
    import javafx.scene.shape.LineTo;
    import javafx.scene.shape.MoveTo;
    import javafx.scene.shape.Path;
    import javafx.scene.text.Font;
    import javafx.scene.text.Text;
    import javafx.stage.Stage;
    import javafx.util.Duration;

    public class Main extends Application {

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

        @Override
        public void start(Stage primaryStage) throws Exception {
            Pane root = new Pane();
            Scene scene = new Scene(root);
            root.setCache(false);
            primaryStage.setTitle("Hello World");
            primaryStage.setScene(scene);


            Path path = new Path();
            root.widthProperty().addListener((observableValue, oldSceneWidth, newSceneWidth) -> SetPathElements(path, root));
            root.heightProperty().addListener((observableValue, oldSceneWidth, newSceneWidth) -> SetPathElements(path, root));


            Duration duration = Duration.millis(1000);

            scene.setOnKeyPressed(event -> {
                System.gc();

                Text textNode = new Text(event.getText());
                textNode.setFont(Font.font(50));
                textNode.setFill(Color.ORANGE);
                root.getChildren().add(textNode);


                PathTransition pathTransition = new PathTransition();
                pathTransition.setDuration(duration);
                pathTransition.setPath(path);
                pathTransition.setCycleCount(1);

                pathTransition.setNode(textNode);
                pathTransition.setOnFinished(event1 -> {
                    root.getChildren().remove(textNode);
                    pathTransition.setNode(null);
                    pathTransition.setPath(null);
                    textNode.setFont(null);
                    textNode.setFill(null);
                });
                pathTransition.play();


            });
            primaryStage.show();
        }

        private void SetPathElements(Path path, Pane root) {
            path.getElements().clear();
            double w = root.getWidth();
            double h = root.getHeight();
            path.getElements().add(new MoveTo(w / 2, h));
            path.getElements().add(new LineTo(w / 2, -40));
        }
    }



EDIT #1

OS: Arch Linux 64-bit Platform: Intel i7-3rd generation, 8 GB ram IDE : Intellij JDK : 1.8.0_102

Proof of leak : After typing around 100 chars it jumped from 50 MB to 1.3 GB Memory leakage proof


EDIT #2

I have checked Heap size using jvisualvm and it indicates that the Heap expands greatly but the used portion don't exceed ~50 MB enter image description here

like image 754
Shady Atef Avatar asked Mar 17 '26 06:03

Shady Atef


2 Answers

There is a memory leak in JavaFX with Mesa >=11.0 (meaning any up to date Linux distribution). JavaFX developers say it's a bug in Mesa, but I couldn't find a bug report in Mesa (nor could I file one, as I don't know how to reproduce it outside of JavaFX).
The only solutions as of now are -
1. Use an older Linux (the key is having Mesa 10 or lower)
2. Use an NVidia GPU - they have their own OpenGL implementation and don't rely on Mesa.
3. Use Windows.

Update (November 2016)
This issue seems to have been resolved in newer versions of Mesa and/or X.org. Updating to Mesa 13.0 and X.org >=1.18.4 should solve this issue.

Related links:

  • openjfx-dev discussion thread.
  • reddit discussion.
  • Mesa discussion.
  • Related SO post: JavaXF 8 ProgressBar and ProgressIndicator with process=-1 memory leak on Linux
like image 52
Itai Avatar answered Mar 18 '26 19:03

Itai


The upgrade up to Mesa 13.0.4 does not fix the issue, but there is a workaround.

If the program is run with -Dprism.order=j2d or -Dprism.order=sw VM argument, JavaFX rendering engine does not use OpenGL, and the leak does not happen. Of course, the application performance is significantly degraded in this case.

like image 27
elmot Avatar answered Mar 18 '26 20:03

elmot