Comment voir le code compilé par JIT dans JVM?

Existe-t-il un moyen de voir le code natif produit par JIT dans une JVM?

En supposant que vous utilisez la JVM Sun Hotspot (c’est-à-dire celle fournie sur java.com par Oracle), vous pouvez append 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 rest.

Si vous voulez voir le bytecode entier, y compris les parties non optimisées, ajoutez

-XX: ComstackThreshold = #

lorsque vous exécutez votre code.

Vous pouvez en savoir plus sur cette commande et les fonctionnalités de JIT en général ici .

Usage général

Comme expliqué par d’autres réponses, vous pouvez exécuter 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:ComstackCommand=print,*MyClass.myMethod 

Remarques:

  • vous devrez peut-être mettre le deuxième argument entre guillemets en fonction du système d’exploitation, etc.
  • Si la méthode est mise en ligne, vous risquez de manquer certaines optimisations

Comment: installer les bibliothèques requirejses sous Windows

Si vous exécutez Windows, cette page contient des instructions sur la façon de créer 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 des binarys prédéfinis

Vous pouvez télécharger des binarys pré-construits pour Windows à partir du projet fcml

  • hsdis-amd64.dll
  • hsdis-i386.dll

Comment comstackr hsdis-amd64.dll et hsdis-i386.dll sous Windows

Cette version du guide a été préparée sur Windows 8.1 64 bits en utilisant Cygwin 64 bits et produisant hsdis-amd64.dll

  1. Installez Cygwin . À 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 )
  2. Exécutez le terminal Cygwin. Cela peut être fait à l’aide de l’icône Desktop ou Start Menu créée par le programme d’installation et créera votre répertoire de base Cygwin (par défaut C:\cygwin\home\\ ou C:\cygwin64\home\\ ). .

  3. Téléchargez le dernier paquet source GNU binutils et extrayez son contenu dans votre répertoire personnel Cygwin. Au moment de la rédaction de ce document, le dernier paquet est binutils-2.25.tar.bz2 . Cela devrait aboutir à un répertoire nommé binutils-2.25 (ou à la dernière version) dans votre répertoire de base Cygwin.
  4. Téléchargez la source OpenJDK en accédant au référentiel JDK 8 Updates , en sélectionnant la balise correspondant à votre version de JRE installée, puis en cliquant sur bz2. Extrayez le répertoire hsdis (trouvé dans src\share\tools ) dans votre répertoire de base Cygwin.
  5. Dans le terminal Cygwin, entrez cd ~/hsdis .
  6. Pour générer hsdis-amd64.dll , entrez

    make OS=Linux MINGW=x86_64-w64-mingw32 'AR=$(MINGW)-ar' BINUTILS=~/binutils-2.25

    Pour générer hsdis-i386.dll , entrez

    make OS=Linux MINGW=i686-w64-mingw32 'AR=$(MINGW)-ar' BINUTILS=~/binutils-2.25

    Dans les deux cas, remplacez la version 2.25 par la version 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 de hsdis ne le reconnaît pas comme tel.

  7. La compilation échouera avec les messages ./chew: No such file or directory et gcc: command not found . Editez \hsdis\build\Linux-amd64\bfd\Makefile dans un éditeur de texte comme Wordpad ou Notepad ++ pour changer SUBDIRS = doc po (ligne 342, si vous utilisez binutils 2.25) en 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 dans 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é des autres options PrintAssembly utilisées.

* la licence de la page est Creative Commons

Vous avez besoin d’un plugin hsdis pour utiliser PrintAssembly . Le plug-in hsdis basé sur la bibliothèque FCML est un choix pratique.

Il peut être compilé pour des systèmes de type UNIX et sous Windows, vous pouvez utiliser des bibliothèques préconfigurées disponibles dans la section de téléchargement FCML de Sourceforge:

Pour installer dans Windows:

  • Extrayez le fichier dll (il peut être trouvé dans hsdis-1.1.2-win32-i386.zip et hsdis-1.1.2-win32-amd64.zip).
  • Copiez le java.dll DLL là où il existe 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

Pour installer sous Linux:

  • Téléchargez le code source, extrayez-le
  • cd
  • ./configure && make && sudo make install
  • cd example/hsdis && make && sudo make install
  • sudo ln -s /usr/local/lib/libhsdis.so /lib/amd64/hsdis-amd64.so
  • sudo ln -s /usr/local/lib/libhsdis.so /jre/lib/amd64/hsdis-amd64.so
  • Sur mon système, le JDK se trouve 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 Code machine avant le mnémonique.
intel Utilisez la syntaxe Intel.
gas Utilisez la syntaxe de l’assembleur AT & T (compatible avec l’assembleur GNU).
dec Imprime IMM et le déplacement en tant que valeurs décimales.
mpad = XX Rembourrage pour la partie mnémonique de l’instruction.
cpad = XX Rembourrage pour le code machine.
seg Affiche les registres de segment par défaut.
zeros Affiche les zéros en tête pour les littéraux HEX.

La syntaxe Intel est une syntaxe par défaut dans le cas de Windows, tandis que la syntaxe AT & T est utilisée 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 (Sun), même dans les modes du produit:

http://wikis.oracle.com/display/HotSpotInternals/PrintAssembly

Quelques assemblages requirejs: il faut un plugin.

Je crois que WinDbg serait utile si vous l’exécutez sur une machine Windows. Je viens de lancer un pot.

  • Puis je me suis attaché au processus java via Windbg
  • Examen des threads par ~ commande; Il y avait 11 threads, 0 thread était le thread de travail principal
  • Passé à 0-thread – ~ 0s
  • En regardant à travers un appel non géré, 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 sont exécutées en code JIT direct sur JVM.

  • Ensuite, nous pouvons rechercher l’adresse de la méthode:
    java + 0x2f68 est 00402f68

  • Sur WinDBG:
    Cliquez sur Afficher -> Désassemblage.
    Cliquez sur Modifier -> Aller à l’adresse.
    Mettez 00402f68
    et a

    00402f68 55 push ebp
    00402f69 8bec mov ebp, esp
    00402f6b 81ec80020000 sous esp, 280h
    00402f71 53 push ebx
    00402f72 56 push esi
    00402f73 57 push edi
    et ainsi de suite

Pour plus d’informations, reportez-vous à l’ exemple suivant: comment retracer le code JIT-ed à partir de fichiers mémoire à l’aide de l’explorateur de processus 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 ont un plug-in Java pour visualiser l’exécution du code Java en tant que code machine.

Imprimez l’assemblage de vos points chauds avec les profileurs de parfum de JMH ( LinuxPerfAsmProfiler ou WinPerfAsmProfiler ). JMH nécessite la bibliothèque hsdis car elle repose sur PrintAssembly .