java jvm startup jsa

java - Acelere el inicio de la aplicación agregando clases de aplicación propias a classes.jsa



jvm startup (4)

Para acelerar el tiempo de inicio de la JVM, los desarrolladores de Sun decidieron que es una buena idea precompilar las clases de tiempo de ejecución estándar para una plataforma durante la instalación de la JVM. Estas clases precompiladas se pueden encontrar, por ejemplo, en:

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

Mi compañía actualmente desarrolla una aplicación independiente de Java que trae su propio JRE, por lo que sería una opción fantástica acelerar el tiempo de inicio de nuestra aplicación agregando nuestras propias clases de aplicación a este archivo jsa también.

No creo que el archivo JSA se haya creado por arte de magia, entonces: ¿Cómo se crea? ¿Y cómo puedo engañar a la JVM para que incorpore mis propias clases?

EDITAR : Ya descubrí lo siguiente:

El comando classes.jsa se crea mediante el comando

java -Xshare:dump

La lista de clases para incorporar en el volcado se puede encontrar en $JAVA_HOME/jre/lib/classlist .

Incluso logré agregar mis propias clases aquí (y agregarlas al rt.jar para que java las encuentre), y generar mi propia suma de comprobación debajo del archivo classlist.

El problema final es que solo se reconocen las clases en los paquetes java, com.sun y org.w3c, si dejo las mismas clases en sus paquetes originales, no se cargarán. Busqué en toda la fuente de OpenJDK un puntero sobre esto, pero parece tener algo que ver con los dominios de protección. Si alguien está lo suficientemente interesado en este tema y conoce lo suficiente, por favor agregue algunos indicadores para que investigue más.


A partir de Java 8u40 (y Embedded Java 8u51), Java ahora es compatible con el uso compartido de datos de la clase de aplicación (AppCDS) (es decir, sus propias clases en el archivo compartido). En nuestra java incrustada, ¡hemos encontrado una mejora de inicio de> 40%! Bastante impresionante por casi ningún trabajo de nuestra parte ...

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


Estabas casi allí, solo necesitas un par de pasos para que funcione. Para agregar sus propias clases a clients.js necesita los siguientes pasos:

  1. El nombre calificado de tus clases (lo tienes)

  2. El classpath de estas clases (lo tienes)

  3. Sepa cómo volver a calcular la suma de comprobación (lo tiene)

  4. Vuelque el nuevo archivo, proporcionando el classpath de las clases que está precompilando con las clases de Java.

  5. Ejecute el programa, proporcionando el mismo classpath que utilizó para volcar las nuevas clases.jsa

Para proporcionar el classpath donde están las clases que está agregando a la lista de clase, use el -Xbootclasspath/a . Anexará los directorios / JAR cuando JVM esté buscando los lugares donde están las clases de arranque. El espacio predeterminado para classes.jsa es bastante pequeño, si necesita mejorarlo puede usar los -XX:SharedReadWriteSize y -XX:SharedReadOnlySize . Su comando de volcado se ve similar a esto:

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

El último paso es ejecutar la aplicación Java normalmente, recordando activar el modo compartir. También necesita agregar el Xbootclasspath excatly como lo agregó en el volcado. Se verá de manera similar a esto:

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

Ahora, todas las clases que coloca en la lista de clases se comparten con otras instancias que se ejecutan en la misma JVM.


Idea interesante. Sin embargo, mientras lo leo, se usa para compartir datos entre máquinas virtuales y para acelerar la carga de clases, no para compilar. No estoy seguro de cuánto impulso obtendría, pero podría valer la pena intentarlo si ya tiene un gran retraso en el inicio (aunque la VM ya intenta mitigar eso).

En cuanto a intentarlo usted mismo, parece que este archivo normalmente se crea cuando se instala Sun VM, pero también puede controlarlo. Algunos detalles se encuentran en este documento más antiguo sobre el intercambio de datos de Sun Java 5 Class (¿es posible que ya lo haya visto?). Algunos documentos de Sun Java 6 también lo mencionan algunas veces , pero no agregan mucho a la documentación. Parece que originalmente era una función de VM de IBM . Y, para continuar el volcado de enlaces, se explica un poco en este artículo .

Personalmente, no sé mucho al respecto, así que no sé cómo puedes controlarlo. Puedes regenerarlo, pero no creo que esté destinado a que pongas cosas personalizadas. Además, incluso si puede "engañarlo", eso probablemente violaría una licencia de Sun / Oracle de algún tipo (no puede meterse con rt.jar y redistribuir, por ejemplo). Y, dicho todo eso, dudo que veas una mejora seria en el tiempo de inicio a menos que tengas miles o decenas de miles de clases en tu aplicación.

(Y esta no es realmente una respuesta, lo sé, pero era demasiado grande para encajar en un comentario, y encontré la pregunta interesante, así que investigué un poco y puse enlaces aquí en caso de que alguien encuentre útil la misma información).


Me costó un poco descifrarlo, pero tengo 4 Java8 VM (versión 1.8.0_162) ejecutándose con clases compartidas. La siguiente secuencia de comandos se usó para configurar y probar compartir y con una pequeña modificación podría usarse en otra parte:

#!/bin/bash # Libraries to load LIBS1="./lib/protobuf-java-2.6.1.jar:/ ./lib/jetty-server-9.2.18.v20160721.jar:./lib/jetty-util-9.2.18.v20160721.jar:./lib/servlet-api-3.1.jar:./lib/jetty-http-9.2.18.v20160721.jar:./lib/jetty-io-9.2.18.v20160721.jar:/ ./lib/derby.jar:/ ./lib/json-simple-1.1.1.jar:" LIBS2=":./lib/GTFS.jar" # Uncomment these lines for the first phase where you are determining the classes to archive. During this phase aim to get as many classes loaded as possible # which means loading a schedule and retrieving the stop list and next vehicle information # #APPCDS="-Xshare:off -XX:+UnlockCommercialFeatures -XX:+UseAppCDS -XX:DumpLoadedClassList=../GtfsAppCds.lst" #java -Xmx512m $APPCDS -Dderby.system.home=database -classpath $LIBS1$LIBS2 com.transitrtd.GtfsOperatorManager # Uncomment these lines when the class list is created and run to create the shared archive. Classes marked as unverifiable will need to be removed from the # archived class list in GtfsAppCds.lst and the lines below run again. LIBS2 above contains jars which are left out of the archive. These are jars which change # frequently and would therefore cause the archive to be frequently rebuilt. # #APPCDS="-Xshare:dump -XX:+UnlockCommercialFeatures -XX:+UseAppCDS -XX:SharedClassListFile=../GtfsAppCds.lst -XX:SharedArchiveFile=../GtfsAppCds.jsa" #java -Xmx512m $APPCDS -classpath $LIBS1 # Uncomment these lines when wishing to verify the application is using the shared archive. # #APPCDS="-Xshare:on -XX:+UnlockCommercialFeatures -XX:+UseAppCDS -XX:SharedArchiveFile=../GtfsAppCds.jsa -verbose:class" #java -Xmx512m $APPCDS -Dderby.system.home=database -classpath $LIBS1$LIBS2 com.transitrtd.GtfsOperatorManager

Tenga en cuenta que el archivo de almacenamiento compartido (iethe jsa file) depende de la arquitectura y tendrá que construirse en cada tipo de plataforma de destino.

Además, si un contenedor utiliza paquetes sellados, se lanza una excepción de seguridad, consulte

https://docs.oracle.com/javase/tutorial/deployment/jar/sealman.html

para información sobre paquetes sellados. Este fue el caso anterior con derby.jar, pero el problema podría resolverse desempaquetando el archivo jar, reemplazando Sellado: verdadero con Sellado: falso en el manifiesto y reempaqueándolo.

Los archivos jar creados con versiones anteriores de java no se pueden usar en un archivo compartido, en el caso anterior a la versión de derby es necesario actualizar de 10.10 a 10.14 para beneficiarse.