Existe-t-il un moyen de voir le code natif produit par le JIT dans une machine virtuelle Java?
Si vous utilisez la machine virtuelle Java Sun Hotspot (c'est-à-dire celle fournie sur Java.com par Oracle), vous pouvez ajouter l'indicateur.
-XX: + PrintOptoAssembly
lors de l'exécution de votre code. Ceci imprimera le code optimisé généré par le compilateur JIT et laissera le reste.
Si vous voulez voir tout le bytecode, 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 .
Comme expliqué par d'autres réponses, vous pouvez exécuter avec les options JVM suivantes:
-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly
Vous pouvez également filtrer sur une méthode spécifique avec la syntaxe suivante:
-XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*MyClass.myMethod
Remarques:
Si vous utilisez Windows, cette page contient des instructions sur la construction et l’installation de hsdis-AMD64.dll
et hsdis-i386.dll
nécessaires à son bon fonctionnement. Nous copions ci-dessous et étendons le contenu de cette page * pour référence:
Où trouver les binaires pré-construits
Vous pouvez télécharger des fichiers binaires prédéfinis pour Windows à partir du projet fcml
Comment compiler hsdis-AMD64.dll
et hsdis-i386.dll
sous Windows
Cette version du guide a été préparée sous Windows 8.1 64 bits avec Cygwin 64 bits et produisant hsdis-AMD64.dll .
Installer Cygwin . Sur l'écran Select Packages
, ajoutez les packages suivants (en développant la catégorie Devel
, puis en cliquant une fois sur l'étiquette Skip
à côté de chaque nom de package):
make
mingw64-x86_64-gcc-core
(nécessaire uniquement pour hsdis-AMD64.dll
)mingw64-i686-gcc-core
(nécessaire uniquement pour hsdis-i386.dll
)diffutils
(dans la catégorie Utils
)Exécutez le terminal Cygwin. Cela peut être effectué à l'aide de l'icône du bureau ou du menu Démarrer créée par le programme d'installation et créera votre répertoire de base Cygwin (C:\cygwin\home\<username>\
ou C:\cygwin64\home\<username>\
par défaut).
binutils-2.25.tar.bz2
. Cela devrait donner lieu à un répertoire nommé binutils-2.25
(ou quelle que soit la version la plus récente) dans votre répertoire personnel Cygwin.src\share\tools
) dans votre répertoire de base Cygwin.cd ~/hsdis
.Pour construire hsdis-AMD64.dll
, entrez
make OS=Linux MINGW=x86_64-w64-mingw32 'AR=$(MINGW)-ar' BINUTILS=~/binutils-2.25
Pour construire hsdis-i386.dll
, entrez
make OS=Linux MINGW=i686-w64-mingw32 'AR=$(MINGW)-ar' BINUTILS=~/binutils-2.25
Dans les deux cas, remplacez 2.25
par la version de binutils que vous avez téléchargée. OS=Linux
est nécessaire car, bien que Cygwin soit un environnement de type Linux, le fichier makefile hsdis ne parvient pas à le reconnaître en tant que tel.
./chew: No such file or directory
et gcc: command not found
. Modifiez <Cygwin home directory>\hsdis\build\Linux-AMD64\bfd\Makefile
dans un éditeur de texte tel que Wordpad ou Notepad ++ pour modifier SUBDIRS = doc po
(ligne 342, si vous utilisez binutils 2.25) en SUBDIRS = po
. Relancez la commande précédente.La DLL peut maintenant être installée en la copiant du répertoire hsdis\build\Linux-AMD64
ou hsdis\build\Linux-i586
dans le répertoire _ de votre JRE bin\server
ou bin\client
. Vous pouvez trouver tous ces répertoires sur votre système en recherchant Java.dll
.
Conseil bonus: si vous préférez la syntaxe Intel ASM à AT & T, spécifiez -XX:PrintAssemblyOptions=intel
à côté de toute autre option PrintAssembly que vous utilisez.
* La licence de la 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 des systèmes de type UNIX et sous Windows, vous pouvez utiliser des bibliothèques prédéfinies disponibles dans la section FCML download de Sourceforge:
Java.dll
(utilisez la recherche Windows). 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
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
Paramètres de configuration supplémentaires:
code Imprimez le code machine avant le mnémonique.
intel Utilisez la syntaxe Intel.
gaz Utilisez la syntaxe de l'assembleur AT & T (compatible avec l'assembleur GNU).
déc Imprime IMM et le déplacement sous forme décimale.
mpad = XX Rembourrage pour la partie mnémonique de l'instruction.
cpad = XX Rembourrage pour le code machine.
seg Affiche les registres de segments par défaut.
des zéros Montre les zéros de gauche dans le cas de littéraux HEX.
La syntaxe Intel est celle par défaut sous Windows, tandis que celle AT & T est celle par défaut pour GNU/Linux.
Pour plus de détails, voir Manuel de référence de la bibliothèque FCML
Pour la machine virtuelle Java HotSpot (anciennement Sun), même dans les modes de produit:
http://wikis.Oracle.com/display/HotSpotInternals/PrintAssembly
Assemblage requis: il faut un plugin.
Je pense que WinDbg serait utile si vous l’exécutez sur une machine Windows ..__ Je viens d’en lancer un.
Regardé par kb à travers une pile d'appels non gérée, 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 correspondent à l'exécution directe du code JIT sur la JVM.
Ensuite, nous pouvons rechercher l'adresse de la méthode:
Java + 0x2f68 est 00402f68
Sur WinDBG:
Cliquez sur Afficher -> Désassemblage.
Cliquez sur Edition -> Aller à l'adresse
Mettez 00402f68 ici
et j'ai
00402f68 55 ebp push
00402f69 8bec mov ebp, esp
00402f6b 81ec80020000 sous esp, 280h
00402f71 53 Push ebx
00402f72 56 Appuyez sur cette touche
00402f73 57 Push edi
... etc
Pour plus d'informations, voici Exemple comment retrouver le code JIT à partir de vidages de mémoire à l'aide de Process Explorer et de WinDbg.
Une autre façon de voir le code machine et certaines données de performance consiste à utiliser CodeAnalyst ou OProfile d'AMD, qui disposent d'un plugin Java pour visualiser le code Java en cours d'exécution en tant que code machine.
Imprimez l'assemblage de vos points d'accès avec les profileurs de perfasm de JMH (LinuxPerfAsmProfiler
ou WinPerfAsmProfiler
). JMH requiert la bibliothèque hsdis
car elle repose sur PrintAssembly
.