Comment voir le code compilé JIT dans JVM?
Existe-t-il un moyen de voir le code natif produit par le JIT dans une JVM?
7 réponses
En supposant que vous utilisez la JVM Sun Hotspot (c'est-à-dire celle fournie sur java.com par Oracle), vous pouvez ajouter le drapeau
- XX: + PrintOptoAssembly
Lors de l'exécution de votre code. Cela imprimera le code optimisé généré par le compilateur JIT et laissera de côté le reste.
Si vous voulez voir le bytecode entier, y compris les parties non optimisées, ajoutez
- XX: CompileThreshold=#
Lorsque vous exécutez votre code.
Vous pouvez en savoir plus sur cette commande et la fonctionnalité de JIT en général ici .
Générales d'utilisation de
Comme expliqué par d'autres réponses, vous pouvez exécuter avec les options JVM suivantes:
-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly
Filtrer sur une méthode spécifique
, Vous pouvez également filtrer sur une méthode spécifique avec la syntaxe suivante:
-XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*MyClass.myMethod
Notes:
- vous devrez peut-être mettre le deuxième argument entre guillemets en fonction du système d'exploitation, etc.
- si la méthode est InLine, vous pourriez manquer certaines optimisations
Comment: installer les bibliothèques requises sur Fenêtres
Si vous utilisez Windows, cette page contient des instructions sur la façon de construire et d'installer hsdis-amd64.dll
et hsdis-i386.dll
, qui sont nécessaires pour le faire fonctionner. Nous copions ci-dessous et étendons le contenu de cette page* pour référence:
Où trouver les binaires prédéfinis
Vous pouvez télécharger des binaires prédéfinis pour Windows à partir du fcml projet
Comment construire hsdis-amd64.dll
et hsdis-i386.dll
sur Windows
cette version du guide a été préparée sur Windows 8.1 64bit en utilisant Cygwin 64 bits et en produisant hsdis-amd64.dll
-
Installer Cygwin. À l'écran
Select Packages
, ajoutez les paquets suivants (en développant la catégorieDevel
, puis en cliquant une fois sur l'étiquetteSkip
à côté de chaque paquet nom):make
-
mingw64-x86_64-gcc-core
(seulement nécessaire pourhsdis-amd64.dll
) -
mingw64-i686-gcc-core
(seulement nécessaire pourhsdis-i386.dll
) -
diffutils
(dans la catégorieUtils
)
Exécutez le Terminal Cygwin. Cela peut être fait en utilisant L'icône du bureau ou du Menu Démarrer créée par le programme d'installation, et créera votre répertoire personnel Cygwin (
C:\cygwin\home\<username>\
ouC:\cygwin64\home\<username>\
par défaut).-
Téléchargez le dernier paquet source GNU binutils et extrayez son contenu dans votre maison Cygwin répertoire. Au moment de la rédaction, le dernier paquet est
binutils-2.25.tar.bz2
. Cela devrait aboutir à un répertoire nommébinutils-2.25
(ou quelle que soit la dernière version) dans votre répertoire personnel Cygwin. - Téléchargez la source OpenJDK en accédant au référentiel JDK 8 Updates , en sélectionnant la balise correspondant à votre version JRE installée et en cliquant sur bz2. Extrayez le répertoire hsdis (trouvé dans
src\share\tools
) dans votre répertoire personnel Cygwin. - dans le Terminal Cygwin, entrez
cd ~/hsdis
. -
Pour construire
hsdis-amd64.dll
, entrezmake OS=Linux MINGW=x86_64-w64-mingw32 'AR=$(MINGW)-ar' BINUTILS=~/binutils-2.25
Pour construire
hsdis-i386.dll
, entrezmake OS=Linux MINGW=i686-w64-mingw32 'AR=$(MINGW)-ar' BINUTILS=~/binutils-2.25
Dans les deux cas, remplacez
2.25
par la version binutils que vous avez téléchargée. {[27] } est nécessaire car, bien que Cygwin soit un environnement de type Linux, le fichier makefile hsdis ne le reconnaît pas comme tel. - la construction échouera avec les messages
./chew: No such file or directory
etgcc: command not found
. Modifier<Cygwin home directory>\hsdis\build\Linux-amd64\bfd\Makefile
dans un éditeur de texte comme Wordpad ou Notepad++ pour changerSUBDIRS = doc po
(ligne 342, si en utilisant binutils 2.25) àSUBDIRS = po
. Réexécutez la commande précédente.
La DLL peut maintenant être installée en la copiant depuis hsdis\build\Linux-amd64
ou hsdis\build\Linux-i586
vers le répertoire bin\server
ou bin\client
de votre JRE. Vous pouvez trouver tous ces répertoires sur votre système en recherchant java.dll
.
Astuce Bonus: si vous préférez la syntaxe Intel ASM à AT & T, spécifiez -XX:PrintAssemblyOptions=intel
à côté de toutes les autres options D'assemblage D'impression que vous utilisez.
*la licence de page est Creative Commons
Vous avez besoin d'un plugin hsdis pour utiliser PrintAssembly
. Un choix pratique est le plugin hsdis basé sur la bibliothèque FCML.
Il peut être compilé pour les systèmes de type UNIX et sous Windows, vous pouvez utiliser des bibliothèques pré-construites disponibles dans la section FCML download sur Sourceforge:
Pour installer dans Windows:
- extrayez la dll (elle peut être trouvée dans hsdis-1.1.2-win32-i386.zip et hsdis-1.1.2-win32-amd64.zip).
- copiez la dll où existe
java.dll
(utilisez Windows rechercher). Sur mon système, je l'ai trouvé à deux endroits:C:\Program Files\Java\jre1.8.0_45\bin\server
C:\Program Files\Java\jdk1.8.0_45\jre\bin\server
Pour installer sous Linux:
- Téléchargez le code source, extrayez-le
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
- sur mon système, le JDK est dans
/usr/lib/jvm/java-8-oracle
Comment l'exécuter:
java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly
-XX:+LogCompilation -XX:PrintAssemblyOptions=intel,mpad=10,cpad=10,code
-jar fcml-test.jar
Paramètres de configuration Supplémentaires:
code Imprimer le code machine avant de l' mnémonique.
intel utilise la syntaxe Intel.
gas utilise la syntaxe de l'assembleur AT&T (compatible GNU assembler).
dec affiche IMM et le déplacement en tant que valeurs décimales.
mpad = XX remplissage pour la partie mnémonique de l'instruction.
cpad = XX remplissage pour le code machine.
seg affiche les registres de segment par défaut.
les zéros montrent les zéros en tête dans le cas des littéraux hexadécimaux.
La syntaxe Intel est un un par défaut dans le cas de Windows, alors que L'AT & T est un par défaut pour GNU / Linux.
Pour plus de détails, voir le manuel de référence de la bibliothèque FCML
Pour la JVM HotSpot (was Sun), même dans les modes produit:
Http://wikis.oracle.com/display/HotSpotInternals/PrintAssembly
Certains assembly requis: il a besoin d'un plugin.
Je crois que WinDbg serait utile si vous l'exécutez sur une machine windows. Je viens d'utiliser un bocal.
- Ensuite, je me suis attaché au processus java à travers Windbg
- fils examinés par ~ commande; il y avait 11 threads, 0 thread était le thread de travail principal
- commuté sur 0-thread - ~0s
-
Regardé à travers callstack non géré par kb Il y avait:
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
Les lignes en surbrillance exécutent directement du code JIT-ed sur JVM.
Ensuite, nous pouvons chercher la méthode de l'adresse:
java+0x2f68 est 00402f68-
Sur WinDBG:
Cliquez Sur Afficher --> Démontage.
cliquez sur Modifier - > aller à Adresse.
Mettez 00402f68 il
et obtenu00402f68 55 push ebp
00402f69 8bec MOV ebp, esp
00402f6b 81ec80020000 sous esp, 280h
00402f71 53 pousser ebx
00402f72 56 pousser esi
00402f73 57 push edi
... et ainsi sur
Pour plus d'informations, voici l'exemple comment retracer le code JIT-ed à partir de vidages de mémoire en utilisant process explorer et WinDbg.
Une autre façon de voir le code machine et certaines données de performance est d'utiliser CodeAnalyst ou OProfile D'AMD, qui ont un plugin Java pour visualiser l'exécution de code Java en tant que code machine.
Imprimez l'assemblage de vos hotspots avec les profileurs perfasm de JMH (LinuxPerfAsmProfiler
ou WinPerfAsmProfiler
). JMH nécessite la bibliothèque hsdis
car elle repose sur PrintAssembly
.