关闭JavaFX Stage后如何释放内存?

时间:2013-02-26 10:09:30

标签: java memory memory-management javafx-2

我正在创建一个JavaFx应用程序,当我点击一个按钮时,它会在新的stage中打开一个表。但我的问题是,当我关闭该表的stage时,应用程序无法释放内存。 javaFX有什么问题吗?或者我还得做点什么?

我试图在关闭该阶段时将所有内容设置为null,但仍然没有释放内存。

桌子上的闭幕事件:

  

TableView tableView;

     

舞台myStage;

this.myStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
            @Override
            public void handle(WindowEvent t) {
                TableController.this.myStage.close();
                tableView.getItems().clear();
                tableView.getColumns().clear();
                tableView = null;
                TableController.this.myStage = null;
                System.gc();
            }
        });

我创建了一个名为 replaceScene 的方法,使用fxml文件为舞台加载场景。它将返回它的控制器并将场景设置到舞台中。

 public static Initializable replaceScene(String fXml, Stage mystage) {
    InputStream in = null;
    try {
        FXMLLoader loader = new FXMLLoader();
        in = Utility.class.getResourceAsStream(fXml);
        loader.setLocation(Utility.class.getResource(fXml));
        loader.setBuilderFactory(new JavaFXBuilderFactory());
        AnchorPane page;
        try {
            page = (AnchorPane) loader.load(in);
        } finally {
            in.close();
        }
        Scene scene = new Scene(page);
        mystage.setScene(scene);
        return loader.getController();
    } catch (Exception ex) {
        return null;
    }
}

我首先获取fxml文件的StreamObject(java.io.InputStream),然后将此streamObject传递给FxmlLoader以加载页面,

  

in = Utility.class.getResourceAsStream(fXml);

我在 输入流对象中 sun.net.www.protocol.jar.JarURLConnection $ JarURLInputStream 的对象

2 个答案:

答案 0 :(得分:8)

内存管理和JavaFX没什么特别之处。如果达到定义的内存限制,GC将运行。设置object = null后它不会运行。 即使调用System.gc()也不意味着GC会运行。来自Javadoc

  

调用gc方法建议 Java虚拟机消耗   努力回收未使用的物体以制造记忆   它们目前可以快速重复使用。

要确定某个地方是否有内存泄漏,您可以使用VisualVM来查看您的应用程序是否(以及为什么)内存不足。

答案 1 :(得分:1)

我即将发布一个非常相似的问题。我必须承认,我不是通过培训的软件工程师,我的应用程序开发风格可能依赖于一些“非细微”的实践和风格。我喜欢Java的一件事是内置内存管理。我不喜欢Java的一件事是内置内存管理。

例如,在Visual Basic 6中,您可以放心,一旦对象的引用计数达到零,它就会被销毁。在Visual Basic 6中实现模式对话框窗口非常简单:

Set myForm = new frmGetClientData
Call myForm.Initialize()
myForm.show, vbModal
nResult = myForm.getResult()
myForm.Hide()
Set myForm = nothing

一旦对myForm的引用被清除,它就会被销毁。这很方便,因为您确信每次都会构建并初始化一个新表单。

在Java中,使用模态对话框窗口非常困难。除非传递引用,否则对话框控制器对象不知道有关父控制器对象的任何信息。类似地,如果父控制器对象需要在其上调用方法,则它必须获得对对话控制器的引用。父控制器在构建新阶段时必须获得对其自己阶段的引用,以便将对话阶段的模态设置为模态。

所有这些引用来回指向,在我看来,在Java中,模态对话框窗口永远不会被垃圾收集(因为指向父窗口和控制器的引用应保持有效)......每次使用FXMLLoader构建和显示对话框窗口时,新的大对象最终会在内存中占用很长的时间。在我看来,在Java中使用模态对话窗口会让你有内存泄漏。

一种解决方案是进入Visual Basic模式,并且在不再使用时,对于释放对话框窗口和控制器的引用是孜孜不倦的。多么麻烦。这仍然无法保证窗口何时被销毁。

另一个解决方案是创建一个对话池并使用初始化方法构建它们,每次需要时将它们设置为已知的初始状态,而不是每次要显示对话框窗口时都构建一个新窗口(就像我想的那样)使用Visual Basic)。

有没有人对JavaFX有这方面的见解?我正在编写一个帮助程序类来帮助我构建和管理模态对话框窗口,但在我看来,这真的不应该是必要的。我可能正在为自己做额外的工作。