java - que - ¿Cómo ver el código compilado JIT en JVM?
jit software (7)
Uso general
Como se explica en otras respuestas, puede ejecutar con las siguientes opciones de JVM:
-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly
Filtrar en un método específico
También puede filtrar en un método específico con la siguiente sintaxis:
-XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*MyClass.myMethod
Notas:
- es posible que deba colocar el segundo argumento entre comillas, según el sistema operativo, etc.
- si el método se inserta, puede perder algunas optimizaciones
Cómo: Instalar las bibliotecas necesarias en Windows
Si está ejecutando Windows, esta página tiene instrucciones sobre cómo construir e instalar hsdis-amd64.dll
y hsdis-i386.dll
que son necesarios para que funcione. Copiamos a continuación y ampliamos el contenido de esa página * como referencia:
Dónde obtener binarios preconstruidos
Puede descargar binarios fcml para Windows desde el proyecto fcml
Cómo construir hsdis-amd64.dll
y hsdis-i386.dll
en Windows
Esta versión de la guía se preparó en Windows 8.1 de 64 bits utilizando Cygwin de 64 bits y produciendo hsdis-amd64.dll
Instala Cygwin . En la pantalla
Select Packages
, agregue los siguientes paquetes (expandiendo la categoríaDevel
, luego haciendo clic una vez en la etiquetaSkip
lado de cada nombre de paquete):-
make
-
mingw64-x86_64-gcc-core
(solo necesario parahsdis-amd64.dll
) -
mingw64-i686-gcc-core
(solo necesario parahsdis-i386.dll
) -
diffutils
(en la categoríadiffutils
)
-
Ejecute la Terminal Cygwin. Esto se puede hacer usando el ícono de escritorio o menú de inicio creado por el instalador, y creará su directorio de inicio de Cygwin (
C:/cygwin/home/<username>/
oC:/cygwin64/home/<username>/
de forma predeterminada) .- Descargue el último paquete fuente de binutils de GNU y extraiga su contenido en el directorio de inicio de Cygwin. En el momento de escribir, el último paquete es
binutils-2.25.tar.bz2
. Esto debería dar como resultado un directorio llamadobinutils-2.25
(o cualquiera que sea la última versión) en su directorio de inicio de Cygwin. - Descargue la fuente de OpenJDK yendo al repositorio de actualizaciones de JDK 8 , seleccionando la etiqueta correspondiente a su versión de JRE instalada y haciendo clic en bz2. Extraiga el directorio hsdis (que se encuentra en
src/share/tools
) en su directorio de inicio de Cygwin. - En la Terminal Cygwin, ingrese
cd ~/hsdis
. Para construir
hsdis-amd64.dll
, ingresemake OS=Linux MINGW=x86_64-w64-mingw32 ''AR=$(MINGW)-ar'' BINUTILS=~/binutils-2.25
Para construir
hsdis-i386.dll
, ingresemake OS=Linux MINGW=i686-w64-mingw32 ''AR=$(MINGW)-ar'' BINUTILS=~/binutils-2.25
En cualquier caso, reemplace
2.25
con la versión binutils que descargó.OS=Linux
es necesario porque, aunque Cygwin es un entorno similar a Linux, el archivo make hsdis no lo reconoce como tal.- La compilación fallará con los mensajes
./chew: No such file or directory
ygcc: command not found
. Edite<Cygwin home directory>/hsdis/build/Linux-amd64/bfd/Makefile
en un editor de texto como Wordpad o Notepad ++ para cambiarSUBDIRS = doc po
(línea 342, si usa binutils 2.25) aSUBDIRS = po
. Vuelve a ejecutar el comando anterior.
La DLL ahora se puede instalar copiándola de hsdis/build/Linux-amd64
o hsdis/build/Linux-i586
en el directorio bin/server
o bin/client
su JRE. Puede encontrar todos esos directorios en su sistema buscando java.dll
.
Consejo de bonificación: si prefiere la sintaxis de Intel ASM a AT & T, especifique -XX:PrintAssemblyOptions=intel
junto con cualquier otra opción de PrintAssembly que utilice.
* la licencia de página es Creative Commons
¿Hay alguna forma de ver el código nativo producido por el JIT en una JVM?
Creo que WinDbg sería útil si lo está ejecutando en la máquina de Windows. Acabo de ejecutar un frasco.
- Luego me uní al proceso de Java a través de Windbg
- Hilos examinados por ~ comando; Hubo 11 hilos, 0 thread was main worker thread
- Cambiado a 0-thread - ~ 0s
Miró a través de callstack no dañado por kb había:
0008fba8 7c90e9c0 ntdll! KiFastSystemCallRet
0008fbac 7c8025cb ntdll! ZwWaitForSingleObject + 0xc
0008fc10 7c802532 kernel32! WaitForSingleObjectEx + 0xa8
0008fc24 00403a13 kernel32! WaitForSingleObject + 0x12
0008fc40 00402f68 java + 0x3a13
0008fee4 004087b8 java + 0x2f68
0008ffc0 7c816fd7 java + 0x87b8
0008fff0 00000000 kernel32! BaseProcessStart + 0x23
Las líneas resaltadas son código JIT-ed de ejecución directa en JVM.
Entonces podemos buscar la dirección del método:
java + 0x2f68 es 00402f68En WinDBG:
Haga clic en Ver -> Desensamblar.
Haga clic en Editar -> Ir a dirección.
Ponga 00402f68 allí
y consiguió00402f68 55 push ebp
00402f69 8bec mov ebp, esp
00402f6b 81ec80020000 sub esp, 280h
00402f71 53 push ebx
00402f72 56 push esi
00402f73 57 push edi
... y así sucesivamente
Para obtener información adicional, aquí está el Example cómo rastrear el código JIT-ed desde los volcados de memoria utilizando Process Explorer y WinDbg.
Imprima el ensamblaje de sus puntos de acceso con los perfiladores de perfil de JMH ( LinuxPerfAsmProfiler
o WinPerfAsmProfiler
). JMH requiere la biblioteca hsdis
ya que depende de PrintAssembly
.
Necesita un complemento hsdis para usar PrintAssembly
. Una opción conveniente es el complemento hsdis basado en la biblioteca FCML.
Se puede compilar para sistemas de tipo UNIX y en Windows puede usar bibliotecas pre compiladas disponibles en la sección de download FCML en Sourceforge:
Para instalar en Windows:
- Extraiga el dll (se puede encontrar en hsdis-1.1.2-win32-i386.zip y hsdis-1.1.2-win32-amd64.zip).
- Copie el
java.dll
a donde existajava.dll
(use la búsqueda de Windows). En mi sistema, lo encontré en dos lugares:-
C:/Program Files/Java/jre1.8.0_45/bin/server
-
C:/Program Files/Java/jdk1.8.0_45/jre/bin/server
-
Para instalar en Linux:
- Descargue el código fuente, extráigalo
-
cd <source code dir>
-
./configure && make && sudo make install
-
cd example/hsdis && make && sudo make install
-
sudo ln -s /usr/local/lib/libhsdis.so <JDK PATH>/lib/amd64/hsdis-amd64.so
-
sudo ln -s /usr/local/lib/libhsdis.so <JDK PATH>/jre/lib/amd64/hsdis-amd64.so
- En mi sistema, el JDK está en
/usr/lib/jvm/java-8-oracle
Cómo ejecutarlo:
java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly
-XX:+LogCompilation -XX:PrintAssemblyOptions=intel,mpad=10,cpad=10,code
-jar fcml-test.jar
Parámetros de configuración adicionales:
código Imprimir código máquina antes de la mnemotécnica.
Intel Usa la sintaxis Intel.
gas Utilice la sintaxis del ensamblador de AT & T (compatible con ensamblador GNU).
dec Imprime el IMM y el desplazamiento como valores decimales.
mpad = XX Relleno para la parte mnemónica de la instrucción.
cpad = XX Relleno para el código de máquina.
seg Muestra los registros de segmentos predeterminados.
ceros Muestra los ceros iniciales en el caso de los literales HEX.
La sintaxis de Intel es una predeterminada en el caso de Windows, mientras que la de AT & T es la predeterminada para GNU / Linux.
Para más detalles, consulte el Manual de referencia de la biblioteca FCML.
Otra forma de ver el código de la máquina y algunos datos de rendimiento es usar CodeAnalyst u OProfile de AMD, que tienen un complemento de Java para visualizar la ejecución del código de Java como código de máquina.
Para el HotSpot (era Sun) JVM, incluso en los modos de producto:
http://wikis.oracle.com/display/HotSpotInternals/PrintAssembly
Requiere ensamblaje: necesita un complemento.
Suponiendo que está utilizando la JVM de Sun Hotspot (es decir, la que proporciona Oracle en java.com ), puede agregar la java.com
-XX: + PrintOptoAssembly
cuando ejecutas tu código Esto imprimirá el código optimizado generado por el compilador JIT y omite el resto.
Si desea ver el bytecode completo, incluidas las partes no optimizadas, agregue
-XX: CompileThreshold = #
cuando estás ejecutando tu código
Puede leer más sobre este comando y la funcionalidad de JIT en general here .