JavaFX吃掉了我的记忆?

jav*_*uns 9 memory performance user-interface javafx javafx-8

在对标题感到沮丧之前,我想清楚一点,我对JavaFX UI更加新鲜.我使用Swing作为开发人员已经有9年了,目前我决定尝试使用JavaFX.网上的例子表明,与Swing相比,JavaFX真的可以创建漂亮的GUI.也许我试图以错误的方式创建和部署GUI,但有一件事是肯定的.JavaFX窗格加载比Swing慢,并消耗更多内存.使用JAVAFX重新设计了相同的GUI,它几乎需要200Mb,而Swing GUI只需要50Mb.

这里我举一个例子,说明如何使用FXML以编程方式创建GUI.

public class PanelCreator {

   private FXMLPane<LoginPaneController>           loginFXML;
   private FXMLPane<RegistrationPaneController>    registerFXML;
   private FXMLPane<EmailValidationPaneController> emailValidationFXML;

   public PanelCreator() {
      this.rootPane = rootPane;
      try {
        loginFXML           = new FXMLPane<LoginPaneController>("Login.fxml");
        registerFXML        = new FXMLPane<RegistrationPaneController>("Register.fxml");
        emailValidationFXML = new FXMLPane<EmailValidationPaneController>("EmailValidation.fxml");
      } catch (IOException e) {e.printStackTrace();} // catch
   } // Constructor Method

   public Pane getLoginPane() {
      return loginFXML.getPane();
   } // getLoginPane()

   public Pane getRegisterPane() {
      return registerFXML.getPane();
   } // getRegisterPane

   public Pane getEmailValidationPane() {
      return emailValidationFXML.getPane();
   } // getEmailValidationPane

   public LoginPaneController getLoginPaneController() {
      return loginFXML.getController();
   } // getLoginPaneController()

   public RegistrationPaneController getRegistrationPaneController() {
      return registerFXML.getController();
   } // getRegistrationPaneController()
} // class PanelCreator
Run Code Online (Sandbox Code Playgroud)

PanelCreator的构造函数方法创建了3个FXMLPane类,这个类结合了FXML窗格及其控制器.FXMLPane类的代码显示在以下代码中.

public class FXMLPane<T> {

    private Pane pane;
    private T paneController;

    public FXMLPane(String url) throws IOException {
        URL location = getClass().getResource(url);
        FXMLLoader fxmlLoader = new FXMLLoader();
        fxmlLoader.setLocation(location);
        fxmlLoader.setBuilderFactory(new JavaFXBuilderFactory());
        pane = fxmlLoader.load(location.openStream());
        paneController = fxmlLoader.<T>getController();
    } // Constructor Method

    public Pane getPane() {
        return pane;
    } // getPane()

    public T getController() {
        return paneController;
    } // getController()
}
Run Code Online (Sandbox Code Playgroud)

通过PanelCreator,我现在可以使用get方法获取每个JavaFX Panel及其控制器,而且每次都不需要运行FXML加载方法来获取面板.目前,困扰我的不是FXML GUI的创建速度比Swing慢,而是RAM的数量是相应的Swing版本的3倍和4倍.

有人可以向我解释我做错了什么吗?FXML文件只有Grid Pane上的基本组件,按钮,图层和文本字段等组件.

Java和JavaFX之间的内存消耗

可以在此处找到上述示例的代码

Zer*_*ono 12

总结评论部分的答案:

  • JavaFX通常需要更多内存.例如,JavaFX对UI组件中的所有属性使用双精度,而Swing大多数时间使用整数值.但差异不应该是显而易见的.
  • Java会根据需要消耗更多内存.默认情况下,即使您触发垃圾回收,Java也不会将内存返回给您的系统.因此,如果JavaFX程序在初始化过程中需要大量内存但在之后释放它,则JRE将继续保持最大内存级别(参见图1).作为副作用,GC的触发次数会减少,因为有大量空闲的未使用内存(见图2).您可以使用JVM选项-XX:+ UseG1GC更改默认值.这会改变内存分配方式,释放方式以及GC触发时的行为.使用此选项,分配的内存应更好地适应已使用的内存.如果您想要更多调优,请参阅Java Heap Tuning
  • 与Swing相比,JavaFX是一个新的框架.随着时间的推移,性能和资源消耗将得到改善.正如您在图1和图3中看到的那样,它已经得到了改进.它现在在64Bit Linux机器上使用8到9MB的内存.这比Swing版本的内存更少.我使用的是Oracle Java

    java version "1.8.0_111"
    Java(TM) SE Runtime Environment (build 1.8.0_111-b14)
    Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode)
    
    Run Code Online (Sandbox Code Playgroud)

JavaFX示例程序随时间的内存消耗. 与使用的内存相比,它显示了大量的可用内存.

图1:JavaFX示例程序随时间的内存消耗.与使用的内存相比,它显示了大量的可用内存.手动触发GC多次以显示没有垃圾的已用内存部分.

JavaFX示例程序随时间的内存消耗,但无需手动触发GC.

图2:JavaFX示例程序随时间的内存消耗,但无需手动触发GC.由于未触发GC,因此使用的内存会增长和增长.

使用GC选项-XX:+ UseG1GC的JavaFX示例程序随时间的内存消耗

图3:使用GC选项-XX:+ UseG1GC的JavaFX示例程序随时间的内存消耗.在第一个GC周期后,内存大小减小到适合使用内存的实际大小.

  • !!! - 可以让 JVM 实际上缩减它从操作系统保留的内存的启示是一个突破,至少对我来说是这样。对我来说,另一个行为长期以来一直是 Java 的主要缺点。是否有专门讨论实现该行为的文本的目标链接? (2认同)
  • 我发现以下摘要文章很有帮助:http://www.stefankrause.net/wp/?p=14 。有了这样的配置,我就不必过多地避免使用基于 JVM 的工具了。 (2认同)