10

我正在创建一个JavaFx应用程序,当我单击一个按钮时,它将在 new 中打开一个表stage。但我的问题是,当我关闭该stage表时,应用程序没有释放内存。javaFX有什么问题吗?还是我必须做其他事情?

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

桌台闭幕式:

表视图表视图;

舞台我的舞台;

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对象

4

2 回答 2

8

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

调用 gc 方法表明Java 虚拟机花费精力回收未使用的对象,以使它们当前占用的内存可用于快速重用。

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

于 2013-02-26T10:19:25.700 回答
2

我正要发布一个非常相似的问题。我必须承认,我不是受过培训的软件工程师,我的应用程序开发风格可能依赖于一些“非细微的”实践和风格。我喜欢 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 所做的那样基本的)。

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

于 2013-03-01T06:42:13.023 回答