优化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.org> = 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,并且不会发生泄漏。 当然,在这种情况下,应用程序性能会显着降低。