2011-01-14 11 views
31

Per accelerare i tempi di avvio della JVM, gli sviluppatori Sun hanno deciso che è consigliabile precompilare le classi di runtime standard per una piattaforma durante l'installazione della JVM. Queste classi precompilate possono essere trovate per es. a:Accelerare l'avvio dell'applicazione aggiungendo classi di applicazioni alle classi.jsa

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

La mia azienda attualmente si sviluppa un'applicazione autonoma Java che porta il proprio JRE, quindi sarebbe una scelta fantastica per accelerare la nostra applicazione ora di inizio aggiungendo anche le nostre classi di applicazione a questo file jsa.

Non credo che il file JSA sia stato creato per magia, quindi: come viene creato? E come posso ingannare la JVM incorporando le mie classi?

EDIT: ho già trovato il seguente:

Il classes.jsa viene creato dal comando

java -Xshare:dump 

L'elenco delle classi a recepire, nella discarica può essere trovato in $JAVA_HOME/jre/lib/classlist.

Sono persino riuscito ad aggiungere le mie classi qui (e ad aggiungerle nel file rt.jar per trovarle) e a generare il mio checksum sotto il file classlist.

Il problema finale è: solo le classi nei pacchetti java, com.sun e org.w3c sembrano essere riconosciute, se lascio le stesse classi nei loro pacchetti originali, non verranno caricate. Ho cercato l'intero sorgente OpenJDK per il puntatore su questo, ma sembra che abbia qualcosa a che fare con i domini di protezione. Se qualcuno è interessato abbastanza a questo argomento e abbastanza informato, per favore aggiungi alcune indicazioni per me per investigaete ulteriormente.

+0

Puoi condividere come ha ricalcolato il checksum? – coppit

+2

Ho trovato la mia risposta in una diapositiva per Java incorporato: c'è un'utilità chiamata AddJsum nell'albero dei sorgenti openjdk. http://www.oracle.com/technetwork/jp/ondemand/java/20110519-java-a-1-greg-400531-ja.pdf – coppit

+0

Grazie, potrei provarlo quando avrò il tempo. – Daniel

risposta

8

A partire da Java 8u40 (e Embedded Java 8u51), Java ora supporta Application Class Data Sharing (AppCDS) (ovvero le proprie classi nell'archivio condiviso). Sul nostro java integrato, abbiamo riscontrato un miglioramento all'avvio> 40%! Abbastanza impressionante per quasi nessun lavoro da parte nostra ...

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

+0

Fantastico! Inizierò a leggerlo immediatamente :)! – Daniel

+0

Esattamente quello che volevo. Purtroppo è disponibile solo come funzionalità commerciale. Ma almeno sembra funzionare. – Daniel

+0

Purtroppo, Oracle ha mantenuto la funzione AppCDS solo per Embedded per la versione 8u51 ... stiamo cercando di ottenere una risposta su se/quando tornerà da Oracle ... ma senza fortuna. Abbiamo avuto una mezza risposta su "Wow - il nostro team di prodotto vorrebbe conoscere la tua esperienza con esso", ma poi non abbiamo mai avuto una risposta su come essere in contatto con loro. – Ben

8

Idea interessante. Mentre lo leggo, viene usato per condividere i dati tra macchine virtuali e per accelerare il caricamento di classi, non per la compilazione. Non sono sicuro di quanto aumento otterresti, ma potrebbe valere la pena provare se hai già un grosso ritardo all'avvio (anche se la VM tenta già di attenuarlo).

Per quanto riguarda il tentativo da soli, sembra che questo file venga normalmente creato quando è installato Sun VM, ma è anche possibile controllarlo. Alcuni dettagli si trovano in questo vecchio documento Sun Java 5 Class Data Sharing (che potresti aver già visto?). Alcuni documenti Sun Java 6 anche mention it a few times, ma non aggiungono molto alla documentazione. Sembra che fosse originariamente un IBM VM feature. E, per continuare il dump del collegamento, è spiegato un po 'in this article.

Personalmente non ne so molto, quindi non so come potreste controllarlo. Puoi rigenerarlo, ma non penso che sia destinato a inserire materiale personalizzato. Inoltre, anche se è possibile "ingannarlo", ciò probabilmente violerebbe una licenza Sun/Oracle di qualche tipo (non si può confondere con rt.jar e ridistribuire, per esempio). E, tutto ciò detto, dubito che vedresti un serio miglioramento nei tempi di avvio a meno che tu non abbia migliaia o decine di migliaia di classi nella tua app?

(E questa non è davvero una risposta, lo so, ma era troppo grande per rientrare in un commento, e ho trovato la domanda interessante quindi ho studiato un po 'e ho messo i link qui nel caso qualcuno trovi le stesse informazioni utile.)

+0

+1 Grazie mille per il tuo grande sforzo. Leggerò i tuoi link e spero di tornare con una soluzione funzionante. Inoltre non sapevo che non mi fosse permesso di giocherellare con il file rt.jar e ridistribuirlo, ma non mi interesserebbe comunque, perché l'unica app che lo usava sarebbe mia. – Daniel

+0

@Charlie, il tuo secondo link è inattivo ....... – Pacerier

11

Eri quasi lì, hai solo bisogno di un paio di passaggi per farlo funzionare. Per aggiungere le tue classi ai clienti.js sono necessari i seguenti passaggi:

  1. Il nome qualificato vostre classi (lo avete)

  2. Il percorso di classe di queste classi (lo avete)

  3. Saper ricalcolare il checksum (ce l'hai)

  4. Scarica il nuovo file, fornendo il classpath delle classi che stai precompilando con le classi Java.

  5. eseguire il programma, fornendo lo stesso percorso di classe che si è utilizzato per scaricare il nuovo classes.jsa

Per fornire il percorso di classe dove sono le classi che si sta aggiungendo al classlist, utilizzare il comando -Xbootclasspath/a. Aggiungerà le directory/i JAR quando JVM sta cercando i luoghi in cui si trovano le classi di avvio. Lo spazio predefinito per classes.jsa è piuttosto ridotto, se è necessario migliorarlo è possibile utilizzare i comandi -XX:SharedReadWriteSize e -XX:SharedReadOnlySize. Il comando dump è l'aspetto seguente:

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

L'ultimo passo è solo eseguire l'applicazione Java normalmente, rememebering del turno sulla modalità di condivisione. È inoltre necessario aggiungere il Xbootclasspath excatly come aggiunto sul dump. Essa sarà simile a questo:

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

Ora ogni classe che si mette sul classlist è condiviso con altre istanze in esecuzione nella stessa JVM.

+0

Sembra fantastico. Lo verificherò sicuramente! – Daniel

+0

Sto provando questo e in mancanza. Ho creato un nuovo file classfile e aggiunto il checksum e specificato -Xbootclasspath/a:/path/to/jars/*. Il file classes.jsa risultante ha le stesse dimensioni dell'originale. È possibile che, come suggerito da Daniel, -Xshare: dump esegua solo il dump delle classi da pacchetti specifici? Il motivo per cui sono interessato a questo è che usiamo un sacco di librerie di terze parti che stanno gonfiando il nostro utilizzo della memoria RSS.Sarebbe bello ottenere queste condivisioni tra JVM come la libreria standard. (E sì, ho visto le precauzioni nelle domande collegate.;)) – coppit

+0

Stai sostituendo il file 'classlist' con la tua versione modificata? –

Problemi correlati