¿Hay alguna forma de ver el código nativo producido por el JIT en una JVM?
¿Hay alguna forma de ver el código nativo producido por el JIT en una JVM?
Respuestas:
Suponiendo que está utilizando Sun Hotspot JVM (es decir, la proporcionada en java.com por Oracle), puede agregar la bandera
-XX: + PrintOptoAssembly
al ejecutar su código. Esto imprimirá el código optimizado generado por el compilador JIT y omite el resto.
Si desea ver el código de bytes completo, incluidas las partes no optimizadas, agregue
-XX: CompileThreshold = #
cuando está ejecutando su código.
Puede leer más sobre este comando y la funcionalidad de JIT en general aquí .
Como se explica en otras respuestas, puede ejecutar con las siguientes opciones de JVM:
-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly
También puede filtrar por un método específico con la siguiente sintaxis:
-XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*MyClass.myMethod
Notas:
Si está ejecutando Windows, esta página tiene instrucciones sobre cómo compilar e instalar hsdis-amd64.dll
y hsdis-i386.dll
cuáles son necesarios para que funcione. Copiamos a continuación y ampliamos el contenido de esa página * como referencia:
Dónde obtener binarios prediseñados
Puede descargar binarios precompilados 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
Instale Cygwin . En la Select Packages
pantalla, agregue los siguientes paquetes (expandiendo la Devel
categoría y luego haciendo clic una vez en la Skip
etiqueta junto al nombre de cada paquete):
make
mingw64-x86_64-gcc-core
(solo se necesita para hsdis-amd64.dll
)mingw64-i686-gcc-core
(solo se necesita para hsdis-i386.dll
)diffutils
(en Utils
categoría)Ejecute la Terminal Cygwin. Esto se puede hacer usando el icono del escritorio o del menú de inicio creado por el instalador, y creará su directorio de inicio de Cygwin ( C:\cygwin\home\<username>\
o C:\cygwin64\home\<username>\
por defecto).
binutils-2.25.tar.bz2
. Esto debería resultar en un directorio llamado binutils-2.25
(o cualquiera que sea la última versión) en su directorio de inicio de Cygwin.src\share\tools
) a su directorio de inicio de Cygwin.cd ~/hsdis
.Para construir hsdis-amd64.dll
, ingrese
make OS=Linux MINGW=x86_64-w64-mingw32 'AR=$(MINGW)-ar' BINUTILS=~/binutils-2.25
Para construir hsdis-i386.dll
, ingrese
make OS=Linux MINGW=i686-w64-mingw32 'AR=$(MINGW)-ar' BINUTILS=~/binutils-2.25
En cualquier caso, reemplácelo 2.25
con la versión de 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.
./chew: No such file or directory
y gcc: command not found
. Edite <Cygwin home directory>\hsdis\build\Linux-amd64\bfd\Makefile
en un editor de texto como Wordpad o Notepad ++ para cambiar SUBDIRS = doc po
(línea 342, si usa binutils 2.25) a SUBDIRS = po
. Vuelva a ejecutar el comando anterior.La DLL ahora se puede instalar copiándola desde hsdis\build\Linux-amd64
o hsdis\build\Linux-i586
hacia su directorio bin\server
o JRE bin\client
. Puede encontrar todos estos directorios en su sistema buscando java.dll
.
-XX:PrintAssemblyOptions=intel
Consejo adicional : si prefiere la sintaxis Intel ASM a AT&T, especifique junto con cualquier otra opción de PrintAssembly que utilice.
* la licencia de la página es Creative Commons
/usr/lib/
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 similares a UNIX y en Windows puede usar bibliotecas preconstruidas disponibles en la sección de descarga de FCML en Sourceforge:
java.dll
(use la búsqueda de Windows). En mi sistema, lo encontré en dos ubicaciones:
C:\Program Files\Java\jre1.8.0_45\bin\server
C:\Program Files\Java\jdk1.8.0_45\jre\bin\server
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
/usr/lib/jvm/java-8-oracle
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:
code Imprime el código de máquina antes del mnemónico.
intel Utilice la sintaxis de Intel.
gas Usa la sintaxis del ensamblador de AT&T (compatible con ensamblador GNU).
dec Imprime IMM y desplazamiento como valores decimales.
mpad = XX Relleno para la parte nemotécnica de la instrucción.
cpad = XX Relleno para el código máquina.
seg Muestra los registros de segmento predeterminados.
ceros Muestra ceros a la izquierda en caso de literales HEX.
La sintaxis de Intel es predeterminada en el caso de Windows, mientras que la de AT&T es predeterminada para GNU / Linux.
Para obtener más detalles, consulte el Manual de referencia de la biblioteca FCML
apt-get install libhsdis0-fcml
( askubuntu.com/a/991166/489909 ). Puede que no sea necesario construirlo usted mismo.
Para HotSpot (antes Sun) JVM, incluso en modos de producto:
http://wikis.oracle.com/display/HotSpotInternals/PrintAssembly
Se requiere algo de ensamblaje: necesita un complemento.
Creo que WinDbg sería útil si lo está ejecutando en una máquina con Windows. Acabo de ejecutar un frasco.
Miró a través de la pila de llamadas no manipulada 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.
Luego podemos buscar la dirección del método:
java + 0x2f68 es 00402f68
En WinDBG:
haga clic en Ver -> Desmontaje.
Haga clic en Editar -> Ir a dirección.
Ponga 00402f68 allí
y obtuve
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 ejemplo de cómo rastrear el código JIT-ed de los volcados de memoria utilizando el explorador de procesos y WinDbg.
Imprima el ensamblaje de sus hotspots con los perfiladores perfasm de JMH ( LinuxPerfAsmProfiler
o WinPerfAsmProfiler
). JMH requiere la hsdis
biblioteca, ya que se basa en PrintAssembly
.