Acelere el inicio de la aplicación agregando clases de aplicación propias a las clases.jsa


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:

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

Mi empresa actualmente desarrolla una aplicación independiente de Java que trae su propio JRE, por lo que sería una opción fantástica para acelerar el tiempo de inicio de nuestra aplicación mediante la adición de nuestras propias clases de aplicación a esta jsa archivo.

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

EDIT : Ya he encontrado lo siguiente:

Las clases.jsa es creado por el comando

java -Xshare:dump

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

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

El problema final es: Solo clases en los paquetes java, com.sun y org.w3c parece ser reconocido, 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 lo suficientemente bien informado, por favor agregue algunos consejos para que investigue más a fondo.

Author: Pacerier, 2011-01-14

4 answers

A partir de Java 8u40 (y Java 8u51 incrustado), Java ahora admite el Uso compartido de datos de Clases de aplicaciones (AppCDS) (es decir, sus propias clases en el archivo compartido). En nuestro java incrustado, hemos encontrado una mejora de inicio de >40%! Bastante impresionante para casi ningún trabajo de nuestra parte...

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

 10
Author: Ben,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-21 13:52:54

Ya casi llegaste, solo necesitas un par de pasos para que funcione. Para añadir tus propias clases a los clientes.js necesita los siguientes pasos:

  1. El nombre calificado de sus clases (usted lo tiene)

  2. El classpath de estas clases (lo tienes)

  3. Saber cómo recalcular la suma de verificación (ya la tienes)

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

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

Para proporcionar la ruta de clase donde están las clases que está agregando a la lista de clases, use el comando -Xbootclasspath/a. Añadirá los directorios / JARs cuando JVM esté buscando los lugares donde están las clases de arranque. El espacio predeterminado para las clases.jsa es bastante pequeña, si necesitas mejorarla puedes usar los comandos -XX:SharedReadWriteSize y -XX:SharedReadOnlySize. Tu comando de volcado te ves similar a esto:

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

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

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

Ahora cada clase que se pone en la lista de clases se comparte con otras instancias que se ejecutan en la misma JVM.

 11
Author: Daniel Pereira,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-27 04:32:54

Interesante idea. Sin embargo, como lo leí, 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 probarlo usted mismo, parece que este archivo se crea normalmente cuando se instala la máquina virtual Sun, pero también puede controlarlo. Algunos detalles se encuentran en los datos de la clase Sun Java 5 Compartir documento (que puede que ya haya visto?). Algunos documentos de Sun Java 6 también lo mencionan varias veces, pero no añaden mucho a la documentación. Parece que originalmente era una característica de IBM VM . Y, para continuar el volcado de enlaces, se explica un poco en este artículo.

Yo personalmente no sé mucho al respecto, así que no se cómo puedes controlarlo. Puedes regenerarlo, pero no creo que esté pensado para que pongas cosas personalizadas. Además, incluso si puedes "truco", que probablemente violaría una licencia de Sun / Oracle de algún tipo (no se puede meter con rt.jar y redistribuir, por ejemplo). Y, dicho todo esto, dudo que vea una mejora seria en el tiempo de inicio a menos que tenga miles o decenas de miles de clases en su aplicación.

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

 8
Author: Charlie Collins,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-18 20:53:22

Tomó un poco de averiguación, pero tengo 4 máquinas virtuales Java8 (versión 1.8.0_162) que se ejecutan utilizando clases compartidas. Se utilizó el siguiente script para configurar y probar el uso compartido y, con una pequeña modificación, se podría usar en otro lugar:

#!/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 archivo compartido (es decir, el archivo jsa) depende de la arquitectura y deberá construirse en cada tipo de plataforma de destino.

Además, si un jar utiliza paquetes sellados, se lanza una excepción de seguridad, véase

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

Para información sobre los envases precintados. Este fue el caso anterior con derby.jar pero el problema podría resolverse desempaquetando el archivo jar, reemplazando Sealed:true por Sealed:false en el manifiesto y reempaquetándolo.

Los jars construidos con versiones anteriores de java no se pueden usar en un archivo compartido, en el caso anterior, la versión de derby debía actualizarse desde 10.10 a 10.14 para beneficiarse.

 0
Author: paulh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-18 15:09:17