Shady Atef Shady Atef - 1 month ago 23
Java Question

Optimizing memory leakage in JavaFX

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

Answer

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.

Related links: