优化JavaFX中的内存泄漏

我写了一段代码,让字母出现,然后飞行。 这个问题消耗了大量的内存。

我已经优化了一点点

  • 共享path对象并更新侦听器中的参数。
  • 每次打印新的字母时调用gc

但它仍然使用了大量的内存,所以有关如何减less内存使用的想法?

提前致谢。

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

编辑#1

操作系统:Arch Linux 64位平台:Intel i7-3rd一代,8 GB RAM:IDE:Intellij JDK:1.8.0_102

泄漏证据:input大约100个字符后,它从50 MB跳到1.3 GB 内存泄漏证明


编辑#2

我使用jvisualvm检查堆大小,它表明堆扩展很大,但使用的部分不超过〜50 MB 在这里输入图像描述

JavaFX中存在内存泄漏,Mesa> = 11.0(意味着任何最新的Linux发行版)。 JavaFX开发人员说这是Mesa中的一个bug,但是我在Mesa中找不到一个bug报告(我也不能提交,因为我不知道如何在JavaFX之外重现它)。
目前唯一的解决scheme是 –
1.使用较旧的Linux(关键在Mesa 10或更低)
2.使用NVidia GPU–它们有自己的OpenGL实现,不依赖于Mesa。
3.使用Windows。

更新(2016年11月)
这个问题似乎已经在新版本的Mesa和/或X.org中解决了。 更新到Mesa 13.0和X.or​​g> = 1.18.4 应该解决这个问题。

相关链接:

  • openjfx-dev讨论主题 。
  • reddit讨论 。
  • 梅萨讨论 。
  • 相关SOpost: JavaXF 8 ProgressBar和ProgressIndicator在Linux上的进程= -1内存泄漏

升级到Mesa 13.0.4不能解决问题,但有一个解决方法。

如果程序使用-Dprism.order=j2d-Dprism.order=sw VM参数运行,则JavaFX渲染引擎不使用OpenGL,并且不会发生泄漏。 当然,在这种情况下,应用程序性能会显着降低。