【问题标题】:How to free the memory after closing JavaFX Stage?关闭 JavaFX Stage 后如何释放内存?
【发布时间】:2013-02-11 17:43:14
【问题描述】:

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

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

桌台闭幕式:

TableView 表格视图;

舞台我的舞台;

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

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

【问题讨论】:

    标签: java memory memory-management javafx-2


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

    【讨论】:

      【解决方案2】:

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

      调用 gc 方法建议 Java 虚拟机消耗 努力回收未使用的对象以使内存 它们目前占用可快速重复使用。

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

      【讨论】:

      • 我的意思是说我使用输入流加载场景的方式不会释放内存。
      • @Ronak 你为什么这么认为?在您看来,什么不会被 GC 处理?你用 VisualVM 检查过这个吗?
      • 如果我一次又一次地打开和关闭该表的舞台,那么内存会不断增加。但应在关门活动时减少。
      • @Ronak 再次:当某些东西关闭或设置为 null 时,VM 不会运行垃圾收集(这会导致非常糟糕的性能)。如果您为应用程序提供的内存不足,GC 就会启动。尝试学习 GC 是如何工作的,也许How Garbage Collection works in Java 对你有帮助。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-18
      • 2020-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-15
      • 2013-01-02
      相关资源
      最近更新 更多