web-dev-qa-db-fra.com

Comment voir le code compilé par JIT dans la JVM?

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

69
alsor.net

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 .

39
Falaina

Utilisation générale

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

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 en ligne, vous risquez de manquer certaines optimisations

Comment: installer les bibliothèques requises sous Windows

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 .

  1. 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)
  2. 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).

  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, le dernier package est 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.
  4. Téléchargez le code source OpenJDK par en accédant au référentiel Mises à jour JDK 8 , en sélectionnant la balise correspondant à votre version de JRE installée et en cliquant sur bz2. Extrayez le répertoire hsdis (présent dans src\share\tools) dans votre répertoire de base Cygwin.
  5. Dans le terminal Cygwin, entrez cd ~/hsdis.
  6. 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.

  7. La construction échouera avec les messages ./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

70
assylias

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:

Pour installer sous 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 là où 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écharger le code source, l'extraire
  • 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 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

24
swojtasiak

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.

8
John Rose

Je pense que WinDbg serait utile si vous l’exécutez sur une machine Windows ..__ Je viens d’en lancer un.

  • Ensuite, je me suis joint au processus Java Via Windbg
  • Discussions examinées par la commande ~; Il y avait 11 discussions, 0 thread était le fil de travail principal
  • Commuté sur 0-thread - ~ 0s
  • 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.

5
Andriy Tkach

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.

4
Ian

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.

0