C'è un modo per vedere il codice nativo prodotto da JIT in una JVM?
C'è un modo per vedere il codice nativo prodotto da JIT in una JVM?
Risposte:
Supponendo che tu stia utilizzando Sun Hotspot JVM (ovvero quello fornito su java.com da Oracle), puoi aggiungere il flag
-XX: + PrintOptoAssembly
durante l'esecuzione del codice. Questo stamperà il codice ottimizzato generato dal compilatore JIT e tralascia il resto.
Se vuoi vedere l'intero bytecode, comprese le parti non ottimizzate, aggiungi
-XX: CompileThreshold = #
quando esegui il codice.
Puoi leggere di più su questo comando e sulla funzionalità di JIT in generale qui .
Come spiegato da altre risposte, puoi eseguire con le seguenti opzioni JVM:
-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly
Puoi anche filtrare in base a un metodo specifico con la seguente sintassi:
-XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*MyClass.myMethod
Appunti:
Se utilizzi Windows, questa pagina contiene le istruzioni su come compilare e installare hsdis-amd64.dll
e hsdis-i386.dll
quali sono necessarie per farlo funzionare. Copiamo di seguito ed estendiamo il contenuto di quella pagina * per riferimento:
Dove ottenere i binari predefiniti
È possibile scaricare i binari predefiniti per Windows dal progetto fcml
Come costruire hsdis-amd64.dll
e hsdis-i386.dll
su Windows
Questa versione della guida è stata preparata su Windows 8.1 64bit utilizzando Cygwin a 64 bit e producendo hsdis-amd64.dll
Installa Cygwin . Nella Select Packages
schermata, aggiungi i seguenti pacchetti (espandendo la Devel
categoria, quindi facendo clic una volta Skip
sull'etichetta accanto al nome di ciascun pacchetto):
make
mingw64-x86_64-gcc-core
(necessario solo per hsdis-amd64.dll
)mingw64-i686-gcc-core
(necessario solo per hsdis-i386.dll
)diffutils
(nella Utils
categoria)Esegui il terminale Cygwin. Questo può essere fatto utilizzando l'icona del desktop o del menu Start creata dall'installatore e creerà la directory home di Cygwin ( C:\cygwin\home\<username>\
o C:\cygwin64\home\<username>\
per impostazione predefinita).
binutils-2.25.tar.bz2
. Ciò dovrebbe risultare in una directory denominata binutils-2.25
(o qualunque sia l'ultima versione) nella directory home di Cygwin.src\share\tools
) nella tua home directory di Cygwin.cd ~/hsdis
.Per costruire hsdis-amd64.dll
, entra
make OS=Linux MINGW=x86_64-w64-mingw32 'AR=$(MINGW)-ar' BINUTILS=~/binutils-2.25
Per costruire hsdis-i386.dll
, entra
make OS=Linux MINGW=i686-w64-mingw32 'AR=$(MINGW)-ar' BINUTILS=~/binutils-2.25
In entrambi i casi, sostituisci 2.25
con la versione binutils che hai scaricato. OS=Linux
è necessario perché, sebbene Cygwin sia un ambiente simile a Linux, il makefile hsdis non riesce a riconoscerlo come tale.
./chew: No such file or directory
e gcc: command not found
. Modifica <Cygwin home directory>\hsdis\build\Linux-amd64\bfd\Makefile
in un editor di testo come Wordpad o Notepad ++ per cambiare SUBDIRS = doc po
(riga 342, se usi binutils 2.25) in SUBDIRS = po
. Riesegui il comando precedente.La DLL può ora essere installata copiandola da hsdis\build\Linux-amd64
o hsdis\build\Linux-i586
nella directory bin\server
o JRE bin\client
. Puoi trovare tutte queste directory sul tuo sistema cercando java.dll
.
-XX:PrintAssemblyOptions=intel
Suggerimento bonus: se preferisci la sintassi Intel ASM ad AT&T, specifica insieme a qualsiasi altra opzione PrintAssembly che utilizzi.
* la licenza della pagina è Creative Commons
/usr/lib/
Hai bisogno di un plugin hsdis da usare PrintAssembly
. Una scelta conveniente è il plugin hsdis basato sulla libreria FCML.
Può essere compilato per sistemi tipo UNIX e su Windows è possibile utilizzare librerie predefinite disponibili nella sezione download FCML su Sourceforge:
java.dll
(usa la ricerca di Windows). Sul mio sistema, l'ho trovato in due posizioni:
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
Parametri di configurazione aggiuntivi:
codice Stampa il codice macchina prima dello mnemonico.
intel Usa la sintassi Intel.
gas Usa la sintassi dell'assembler AT&T (compatibile con l'assembler GNU).
dec Stampa IMM e displacement come valori decimali.
mpad = XX Padding per la parte mnemonica dell'istruzione.
cpad = XX Imbottitura per il codice macchina.
seg Mostra i registri di segmento predefiniti.
zeros Mostra gli zeri iniziali in caso di letterali HEX.
La sintassi Intel è quella predefinita nel caso di Windows, mentre quella AT&T è quella predefinita per GNU / Linux.
Per maggiori dettagli vedere il Manuale di riferimento della libreria FCML
apt-get install libhsdis0-fcml
( askubuntu.com/a/991166/489909 ). Costruirlo da soli potrebbe non essere necessario.
Per la JVM HotSpot (era Sun), anche nelle modalità prodotto:
http://wikis.oracle.com/display/HotSpotInternals/PrintAssembly
Richiede un po 'di assemblaggio: necessita di un plugin.
Credo che WinDbg sarebbe utile se lo stai eseguendo su una macchina Windows. Ho appena eseguito un barattolo.
Guardato attraverso lo stack di chiamate non gestito da kb c'era:
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
Le righe evidenziate eseguono direttamente codice JIT su JVM.
Quindi possiamo cercare l'indirizzo del metodo:
java + 0x2f68 è 00402f68
In WinDBG: fare
clic su Visualizza -> Smontaggio.
Fare clic su Modifica -> Vai a indirizzo.
Metti 00402f68 lì
e ottenuto
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
... e così via
Per ulteriori informazioni, ecco l' esempio su come tracciare il codice JIT dai dump della memoria utilizzando Process Explorer e WinDbg.
Stampa l'assemblaggio dei tuoi hotspot con i profilatori perfasm di JMH ( LinuxPerfAsmProfiler
o WinPerfAsmProfiler
). JMH richiede la hsdis
libreria poiché si basa su PrintAssembly
.