JavaFX吃掉了我的记忆?

时间:2015-03-04 19:09:52

标签: performance user-interface memory 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

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()
}

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

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

Memory Consumption Between Java and JavaFX

可以找到上面示例的代码here

1 个答案:

答案 0 :(得分:11)

总结评论部分的答案:

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

Memory consumption over time for the JavaFX example program. It shows a huge amount of free memory compared to the used memory.

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

Memory consumption over time for the JavaFX example program, but without manually triggering the GC.

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

Memory consumption over time for the JavaFX example program using the GC option -XX:+UseG1GC

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