JavaFX吃掉了我的记忆? [英] JavaFX eats my memory?

查看:180
本文介绍了JavaFX吃掉了我的记忆?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



这里我举例说明如何以编程方式创建GUI使用FXML。

 公共类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
} //构造方法

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 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();
} //构造方法

public Pane getPane(){
返回窗格;
} // getPane()

public T getController(){
return paneController;
} // getController()
}

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



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





可以找到上面示例的代码



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





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





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


Before going frustrated about the title, I would like to clear out that I am a fresher on JavaFX UI. I have been a developer for 9 years, using Swing and currently I decided to give a try to the JavaFX. Examples on the net shows that JavaFX really can create beautiful GUIs compared to Swing. Maybe I am trying to create and deploy GUIs the wrong way, but one thing is for sure. JavaFX panes load slower than Swing and consumes a lot more memory. The same GUI was redesigned with JAVAFX and it takes almost 200Mb while the Swing GUI take only 50Mb.

Here I give an example of the code of how I create the GUIs programmatically using FXML.

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

The constructor method of PanelCreator creates 3 FXMLPane classes, a class that combines both the FXML Pane and its Controller. An code of FXMLPane class is shown on the following code.

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

Through PanelCreator now I can use the get methods to get each JavaFX Panel and its controller and I do not have to run the FXML load method every time to get the panel. Currently, what bothers me is not that the creation of FXML GUIs is slower than Swing but more that the RAM is 3x and 4x times more than the correspoing Swing version.

Can someone explain to me what I am doing wrong? The FXML files have just basic components on a Grid Pane, components like buttons, layers and textfields.

The code for the above example can be found here

解决方案

Summarizing the answers from the comment section:

  • JavaFX needs more memory in general. E.g. JavaFX uses double precision for all properties along the UI-components, while Swing uses integer values most of the time. But the difference should not be noticeable.
  • Java consumes more memory as it needs to. As a default Java does not return memory back to your system even if you trigger the garbage collection. Thus if a JavaFX program needs a lot of memory on the initialization process but frees it afterwards, the JRE continues to hold the maximum level of memory for ever (see picture 1). As a side effect the GC will be triggered less often, because there is so much free unused memory (see picture 2). You can change the default by using the JVM option -XX:+UseG1GC. This changes the behavior of how memory is allocated, how it's freed and when the GC is triggered. With this option the allocated memory should better fit in with the used memory. If you want more tuning see Java Heap Tuning
  • JavaFX is a new framework compared to Swing. It will be improved over time in performance and resources consumption. As you can see in picture 1 and 3 it has already been improved. It now uses 8 to 9MB of memory on a 64Bit Linux machine. This is even less memory than the Swing version. I used 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)
    

Picture 1: Memory consumption over time for the JavaFX example program. It shows a huge amount of free memory compared to the used memory. The GC was triggered manually multiple times to show used memory part without garbage.

Picture 2: Memory consumption over time for the JavaFX example program, but without manually triggering the GC. The used memory grows and grows because the GC isn't triggered.

Picture 3: Memory consumption over time for the JavaFX example program using the GC option -XX:+UseG1GC. After the first GC cycle the memory size was reduced to fit the real size of used memory.

这篇关于JavaFX吃掉了我的记忆?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆