Existe-t-il un moyen de voir le code natif produit par le JIT dans une JVM ?
Réponses
Trop de publicités?Usage général
Comme expliqué dans d'autres réponses, vous pouvez fonctionner 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 selon le système d'exploitation, etc.
- si la méthode est inlined, vous pourriez manquer certaines optimisations
Comment faire : Installer les bibliothèques requises sous Windows
Si vous utilisez Windows, cette page explique comment construire et installer hsdis-amd64.dll
et hsdis-i386.dll
qui sont nécessaires pour que cela fonctionne. Je copie ci-dessous le contenu de cette page* pour référence :
Comment construire hsdis-amd64.dll
et hsdis-i386.dll
sur Windows
-
Installer Cygwin . Au
Select Packages
ajoutez les paquets suivants (en développant l'ongletDevel
puis cliquez une fois sur la catégorieSkip
à côté du nom de chaque paquet) :-
make
-
mingw64-x86_64-gcc-core
(uniquement nécessaire pourhsdis-amd64.dll
) -
mingw-gcc-core
(uniquement nécessaire pourhsdis-i386.dll
)
-
-
Exécutez le terminal Cygwin. Vous pouvez le faire en utilisant l'icône du Bureau ou du Menu Démarrer créée par le programme d'installation, et cela créera votre répertoire d'accueil Cygwin (
C:\cygwin\home\username
par défaut). -
Télécharger la dernière version du paquetage source GNU binutils et extraire son contenu dans votre répertoire personnel Cygwin. Au moment où nous écrivons ces lignes, le dernier paquet est le suivant
binutils-2.23.1.tar.bz2
. Cela devrait donner lieu à un répertoire nommébinutils-2.23.1
(ou la dernière version en date) dans votre répertoire personnel Cygwin. -
Téléchargez le dernier paquetage source d'OpenJDK et extraire le
hsdis
(trouvé dansopenjdk\hotspot\src\share\tools
) dans votre répertoire personnel Cygwin. Au moment où nous écrivons ces lignes, le dernier paquet est le suivantopenjdk-7u6-fcs-src-b24-28_aug_2012.zip
. Cela devrait donner lieu à un répertoire nomméhsdis
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 BINUTILS=~/binutils-2.23.1
. Pour construirehsdis-i386.dll
, entrez <make OS=Linux MINGW=i686-pc-mingw32 BINUTILS=~/binutils-2.23.1
. Dans les deux cas, remplacez2.23.1
avec 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 makefile hsdis ne le reconnaît pas comme tel.
La DLL peut maintenant être installée en la copiant à partir de l'adresse suivante hsdis\build\Linux-amd64
ou hsdis\build\Linux-i586
à votre JRE bin\server
ou bin\client
répertoire.
Conseil bonus : si vous préférez la syntaxe ASM d'Intel à celle d'AT&T, indiquez -XX:PrintAssemblyOptions=intel
ainsi que toutes les autres options PrintAssembly que vous utilisez.
*La licence de la page est Creative Commons
En supposant que vous utilisez la JVM Sun Hotspot. Ajoutez le drapeau
-XX:+PrintOptoAssembly
à ce que vous exécutez. Cela n'imprimera que l'assemblage pour le code qui a été JITé (c'est-à-dire que vous ne verrez pas l'assemblage pour les choses non JITées) mais je pense que c'est ce que vous voulez. Si vous voulez voir ce que tout donnerait s'il était JIT, vous pouvez probablement modifier le seuil JIT via :
-XX:CompileThreshold=#
Vous pouvez également utiliser le plugin hsdis basé sur la bibliothèque FCML.
Il peut être compilé pour les systèmes UNIX-like ainsi que pour Windows, mais dans le cas du système Windows, au lieu de construire vos propres binaires (pour autant que je sache, vous êtes obligé de le faire dans le cas de projets basés sur binutils en raison d'incompatibilités de licence), vous pouvez utiliser des bibliothèques pré-construites disponibles dans la section téléchargement :
http://fcml-lib.com/download.html
Le plugin a été testé avec JDK7 et JDK8.
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 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 l'IMM et le déplacement sous forme de valeurs décimales.
mpad=XX Rembourrage pour la partie mnémonique de l'instruction.
cpad=XX Padding pour le code machine.
seg Affiche les registres de segment par défaut.
zéros Afficher les zéros de tête dans le cas des littéraux HEX.
La syntaxe Intel est une syntaxe par défaut dans le cas de Windows, tandis que la syntaxe AT&T est une syntaxe par défaut pour le GNU/Linux.
Pour plus de détails, voir : http://fcml-lib.com/manual.html#examples-hsdis
Pour la JVM HotSpot (anciennement Sun), même en mode produit :
http://wikis.oracle.com/display/HotSpotInternals/PrintAssembly
Un peu de montage est nécessaire : il faut un plugin.
Je pense que WinDbg serait utile si vous l'exécutez sur une machine Windows. Je viens de lancer un jar.
- Puis j'ai attaché au processus java via Windbg
- Fils examinés par ~ commande ; Il y avait 11 threads, 0 thread était le thread de travail principal.
- Passé à 0-fil - ~0s
-
Recherche dans la pile d'appels non gérée 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 surlignées sont l'exécution directe du code JIT sur la JVM.
-
Alors nous pouvons chercher l'adresse de la méthode :
java+0x2f68 est 00402f68 -
Sur WinDBG :
Cliquez sur View --> Démontage.
Cliquez sur Edit --> Go to Adresse.
Mettez 00402f68 là
et a obtenu00402f68 55 pousser ebp
00402f69 8bec mov ebp,esp
00402f6b 81ec80020000 sub esp,280h
00402f71 53 push ebx
00402f72 56 pousser esi
00402f73 57 push edi
... et ainsi de suite
Pour plus d'informations, voici le site Exemple comment retracer du code JIT à partir de vidages de mémoire en utilisant l'explorateur de processus et WinDbg.