2015-03-04 2 views
8

Bevor ich über den Titel frustriert bin, möchte ich klarstellen, dass ich auf JavaFX UI frischer bin. Ich bin seit 9 Jahren Entwickler mit Swing und habe mich entschieden, JavaFX zu testen. Beispiele im Internet zeigen, dass JavaFX wirklich schöne GUIs im Vergleich zu Swing erstellen kann. Vielleicht versuche ich GUIs auf die falsche Art zu erstellen und zu implementieren, aber eines ist sicher. JavaFX-Fenster laden langsamer als Swing und verbrauchen viel mehr Speicher. Die gleiche GUI wurde mit JAVAFX neu gestaltet und benötigt fast 200 MB, während die Swing GUI nur 50 MB benötigt.JavaFX isst mein Gedächtnis?

Hier gebe ich ein Beispiel für den Code, wie ich die GUIs programmgesteuert mit FXML erstellen.

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 

Der Konstruktor von PanelCreator schafft 3 FXMLPane Klassen, eine Klasse, die sowohl die FXML Pane und seine Steuerung kombiniert. Ein Code der FXMLPane-Klasse wird im folgenden Code angezeigt.

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

Durch PanelCreator jetzt kann ich die get-Methoden verwenden, um jeden JavaFX-Panel und seine Controller zu bekommen und ich muß der FXML Load-Methode jedes Mal, um das Panel zu bekommen nicht laufen. Momentan stört mich nicht, dass die Erstellung von FXML-GUIs langsamer als Swing ist, sondern dass der RAM 3x und 4x mehr ist als die entsprechende Swing-Version.

Kann mir jemand erklären, was ich falsch mache? Die FXML-Dateien enthalten nur grundlegende Komponenten in einem Rasterbereich, Komponenten wie Schaltflächen, Ebenen und Textfelder.

Memory Consumption Between Java and JavaFX

Der Code für das obige Beispiel kann here

+0

Haben Sie überprüft, ob der Heap wirklich verbraucht ist? Java verwendet nativen Speicher, wenn er es irgendwann benötigt, aber nie wieder an das Betriebssystem zurückgibt (weil es aus Sicht der Leistung besser ist). Also hast du versucht zu drucken, wie viel Heap übrig ist? – tomsontom

+0

Wie messen Sie den Speicherverbrauch? Können Sie eine einfache Beispielanwendung für eine andere Person zur Verfügung stellen? Führen Sie Ihre vergleichbaren Swing- und JavaFX-Anwendungen auf genau der gleichen Hardware, der gleichen Java-Laufzeitversion und mit denselben Befehlszeilenoptionen aus? – jewelsea

+0

Wirklich zu verstehen, das Speicherverbrauchsverhalten einer Anwendung kann eine schwierige und schwierige Sache sein. Aus dem Code und den Informationen, die Sie bisher zur Verfügung gestellt haben, ist es für andere nicht möglich, den Speicherverbrauch Ihrer Anwendung zu verstehen und zu diagnostizieren, noch konkret festzustellen, was Sie möglicherweise falsch machen. – jewelsea

Antwort

8

Fasst man die Antworten aus dem Kommentarbereich zu finden:

  • JavaFX im Allgemeinen mehr Speicher benötigt. Z.B. JavaFX verwendet doppelte Genauigkeit für alle Eigenschaften entlang der UI-Komponenten, während Swing meistens ganzzahlige Werte verwendet. Aber der Unterschied sollte nicht auffallen.
  • Java verbraucht mehr Speicher als erforderlich. Standardmäßig gibt Java den Speicher nicht zurück an Ihr System, selbst wenn Sie die Garbage Collection auslösen. Wenn also ein JavaFX-Programm während des Initialisierungsprozesses viel Speicher benötigt, es aber danach freigibt, behält die JRE für immer die maximale Speicherebene bei (siehe Abbildung 1). Als Nebeneffekt wird der GC weniger häufig ausgelöst, da so viel freier Speicherplatz frei ist (siehe Bild 2). Sie können den Standardwert ändern, indem Sie die JVM-Option -XX: + UseG1GC verwenden. Dies ändert das Verhalten, wie der Speicher zugewiesen wird, wie er freigegeben wird und wann der GC ausgelöst wird. Mit dieser Option sollte der zugewiesene Speicher besser in den verwendeten Speicher passen. Wenn Sie mehr tun wollen, siehe Java Heap Tuning
  • JavaFX ist ein neues Framework im Vergleich zu Swing. Es wird im Laufe der Zeit in Leistung und Ressourcenverbrauch verbessert werden. Wie Sie in Bild 1 und 3 sehen können, wurde es bereits verbessert. Es verwendet jetzt 8 bis 9 MB Speicher auf einem 64Bit Linux-Rechner. Dies ist noch weniger Speicher als die Swing-Version. Ich habe 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.

Bild 1: Speicherverbrauch im Laufe der Zeit für das JavaFX Beispielprogramm. Es zeigt eine große Menge an freiem Speicher verglichen mit dem verwendeten Speicher. Der GC wurde mehrmals manuell ausgelöst, um den verwendeten Speicherbereich ohne Müll anzuzeigen.

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

Bild 2: Speicherverbrauch im Laufe der Zeit für das Beispielprogramm JavaFX, ohne jedoch die GC manuell auszulösen. Der verwendete Speicher wächst und wächst, weil der GC nicht ausgelöst wird.

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

Abbildung 3: Speicherverbrauch im Laufe der Zeit für das Programm JavaFX Beispiels der GC-Option -XX: + UseG1GC. Nach dem ersten GC-Zyklus wurde die Speichergröße auf die tatsächliche Größe des verwendeten Speichers reduziert.

+0

!!! - Die Enthüllung, dass man die JVM dazu bringen kann, den Speicher, den sie vom Betriebssystem reserviert hat, tatsächlich zu verkleinern, ist für mich zumindest ein Durchbruch. Das andere Verhalten war für Java lange Zeit ein großer Nachteil für mich. Gibt es zielgerichtete Links zu Texten, die speziell über das Erreichen dieses Verhaltens sprechen? – naki

+0

Ich fand die folgende Zusammenfassung writeup hilfreich: http://www.stefankrause.net/wp/?p=14. Bei solchen Konfigurationen muss ich nicht so sehr auf die Verwendung von JVM-basierten Tools verzichten. – naki