2011-01-14 4 views
31

Um die Startzeit der JVM zu beschleunigen, entschieden sich die Sun-Entwickler dafür, die Standardlaufzeitklassen für eine Plattform während der Installation der JVM vorzukompilieren. Diese vorkompilierten Klassen können z.B. an:Beschleunigen Sie den Anwendungsstart durch Hinzufügen eigener Anwendungsklassen zu classes.jsa

$ JAVA_HOME \ jre \ bin \ client \ classes.jsa

derzeit Meine Firma eine Anwendung Java Standalone entwickelt, die ihre eigene JRE bringt, so wäre es eine fantastische Möglichkeit, unsere Anwendung zu beschleunigen Startzeit durch Hinzufügen eigener Anwendungsklassen zu dieser jsa-Datei.

Ich glaube nicht, dass die JSA-Datei durch Magie erstellt wurde, also: Wie wird es erstellt? Und wie kann ich die JVM dazu bringen, meine eigenen Klassen zu integrieren?

EDIT: Ich fand schon folgendes heraus:

Die classes.jsa durch den Befehl erstellt wird

java -Xshare:dump 

Die Liste der Klassen in der Deponie integrieren in $JAVA_HOME/jre/lib/classlist finden.

Ich habe es sogar geschafft, meine eigenen Klassen hier hinzuzufügen (und sie in die rt.jar für java hinzuzufügen, um sie zu finden) und meine eigene Prüfsumme unterhalb der classlist-Datei zu erzeugen.

Das letzte Problem ist: Nur Klassen in den Paketen java, com.sun und org.w3c scheinen erkannt zu werden, wenn ich dieselben Klassen in ihren ursprünglichen Paketen belasse, werden sie nicht geladen. Ich habe die gesamte OpenJDK-Quelle nach einem Zeiger dazu durchsucht, aber es scheint etwas mit Schutzdomänen zu tun zu haben. Wenn jemand genug an diesem Thema interessiert und ausreichend informiert ist, fügen Sie bitte einige Hinweise für mich hinzu, um weiter zu untersuchen.

+0

Können Sie teilen, wie Sie die Prüfsumme neu berechnet? – coppit

+2

Ich habe meine Antwort in einem Slide-Deck für Embedded Java gefunden - es gibt ein Hilfsprogramm namens AddJsum in der openjdk Source-Struktur. http://www.oracle.com/technetwork/jp/ondemand/java/20110519-java-a-1-greg-400531-ja.pdf – coppit

+0

Danke, ich könnte dies ausprobieren, wenn ich die Zeit bekomme. – Daniel

Antwort

8

Ab Java 8u40 (und Embedded Java 8u51) unterstützt Java jetzt Application Class Data Sharing (AppCDS) (dh Ihre eigenen Klassen im gemeinsam genutzten Archiv). Auf unserem Embedded Java haben wir eine Startup-Verbesserung von> 40% gefunden! Ziemlich genial für fast keine Arbeit auf unserer Seite ...

https://blogs.oracle.com/thejavatutorials/entry/jdk_8u40_released

+0

Fantastisch! Ich werde das sofort lesen :)! – Daniel

+0

Genau das, was ich wollte. Leider ist es nur als kommerzielles Feature verfügbar. Aber zumindest scheint es zu funktionieren. – Daniel

+0

Leider hat Oracle die AppCDS-Funktion nur für Embedded für Version 8u51 beibehalten ... wir haben versucht, eine Antwort darauf zu bekommen, ob/wann es von Oracle zurückkommen wird ... aber kein Glück. Wir haben eine halbe Antwort über "Wow - unser Produkt-Team würde gerne Ihre Erfahrung damit wissen", aber dann haben wir nie eine Antwort bekommen, wie man mit ihnen in Kontakt kommt. – Ben

8

Interessante Idee. Wie ich es gelesen habe, wird es für die Freigabe von Daten über VMs und für die Beschleunigung des Classloads verwendet, nicht für die Kompilierung. Ich bin nicht sicher, wie viel von einem Boost Sie bekommen würden, aber es könnte einen Versuch wert sein, wenn Sie bereits beim Start eine große Verzögerung haben (obwohl die VM bereits versucht, dies zu mildern).

Wie Sie es selbst versuchen, scheint diese Datei normalerweise erstellt werden, wenn die Sun VM installiert ist, aber Sie können es auch steuern. Einige Details sind in diesem älteren Sun Java 5 Class Data Sharing Dokument (das Sie vielleicht schon gesehen haben?). Einige Sun Java 6-Dokumente enthalten auch mention it a few times, fügen jedoch nicht viel zur Dokumentation hinzu. Es scheint, dass es ursprünglich ein IBM VM feature war. Und um den Link-Dump fortzusetzen, wird ein bisschen in this article erklärt.

Ich persönlich weiß nicht viel darüber, also weiß ich nicht, wie Sie es kontrollieren könnten. Du kannst es neu generieren, aber ich denke nicht, dass du dafür gedacht bist, benutzerdefiniertes Material einzubauen. Auch wenn Sie es "austricksen" könnten, würde das wahrscheinlich eine Sun/Oracle-Lizenz irgendeiner Art verletzen (Sie können sich beispielsweise nicht mit rt.jar anlegen und neu verteilen). Und, all das gesagt, ich bezweifle, dass Sie eine ernsthafte Verbesserung der Startzeit sehen würden, wenn Sie nicht Tausende oder Zehntausende von Klassen in Ihrer App haben?

(Und das ist nicht wirklich eine Antwort, ich weiß, aber es war zu groß, um in einen Kommentar zu passen, und ich fand die Frage interessant, also habe ich ein wenig untersucht und Links hier für den Fall, dass jemand die gleichen Informationen findet nützlich.)

+0

+1 Vielen Dank für Ihre große Mühe. Ich werde Ihre Links durchlesen und hoffentlich mit einer funktionierenden Lösung zurückkommen. Außerdem wusste ich nicht, dass es mir nicht erlaubt war, mit dem rt.jar herumzuspielen und es neu zu verteilen, aber das würde mich sowieso nicht interessieren, weil die einzige App, die es benutzt, meine wäre. – Daniel

+0

@Charlie, Ihr zweiter Link ist down ....... – Pacerier

11

Sie waren fast da, Sie brauchen nur ein paar Schritte, damit es funktioniert. Um den Clients eigene Klassen hinzuzufügen.js müssen Sie die folgenden Schritte aus:

  1. Der qualifizierte Name Ihre Klassen (Sie es haben)

  2. Der Classpath dieser Klassen (Sie es haben)

  3. Wissen, wie die Prüfsumme neu berechnen (Sie haben es)

  4. Speichern Sie die neue Datei und stellen Sie den Klassenpfad der Klassen bereit, die Sie jetzt mit den Java-Klassen vorkompilieren.

  5. Führen Sie das Programm, das gleiche Classpath vorausgesetzt, Sie haben die neue classes.jsa Dump verwendet

die Classpath bereitzustellen, wo die Klassen sind Sie mit dem Benotungsliste hinzufügen, verwenden Sie den Befehl -Xbootclasspath/a. Es wird die Verzeichnisse/JARs anhängen, wenn JVM die Stellen sucht, an denen sich die Boot-Klassen befinden. Der Standardbereich für die Datei classes.jsa ist ziemlich klein. Wenn Sie ihn verbessern müssen, können Sie die Befehle -XX:SharedReadWriteSize und -XX:SharedReadOnlySize verwenden. Ihr Befehl dump schauen Sie wie folgt aus:

java -Xshare:dump -Xbootclasspath/a:C:/myfiles/directoryA/;C:/myfiles/directoryB/;C:/myJars/myJar.jar; 

Der letzte Schritt ausgeführt wird nur die Java-Anwendung normal, rememebering des Zuges auf den gemeinsamen Modus. Sie müssen auch die excatly hinzufügen, wie Sie auf dem Dump hinzugefügt. Es wird so aussehen:

java myapp.java -Xshare:on -Xbootclasspath/a:C:/myfiles/directoryA/;C:/myfiles/directoryB/;C:/myJars/myJar.jar; 

nun jede Klasse, die Sie auf der Benotungsliste gestellt wird geteilt mit anderen Instanzen in der gleichen JVM ausgeführt wird.

+0

Klingt gut. Ich werde das auf jeden Fall überprüfen! – Daniel

+0

Ich versuche das und schade. Ich habe eine neue classfiles-Datei erstellt und die Prüfsumme hinzugefügt und -Xbootclasspath/a:/path/to/jars/* angegeben. Die resultierende Datei classes.jsa hat dieselbe Größe wie das Original. Ist es möglich, dass, wie Daniel vorgeschlagen hat, der -Xshare: dump nur Klassen von bestimmten Paketen ausgibt? Der Grund, warum ich daran interessiert bin, ist, dass wir eine Menge von 3rd-Party-Bibliotheken verwenden, die unsere RSS-Speicher-Nutzung aufblähen.Es wäre schön, diese JVMs wie die Standard-Bibliothek zu teilen. (Und ja, ich habe die Vorsichtshinweise in den verknüpften Fragen gesehen.;)) – coppit

+0

Ersetzen Sie die 'classlist' Datei durch Ihre modifizierte Version? –

Verwandte Themen