90 votes

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 JVM ?

81voto

assylias Points 102015

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

  1. Installer Cygwin . Au Select Packages ajoutez les paquets suivants (en développant l'onglet Devel puis cliquez une fois sur la catégorie Skip à côté du nom de chaque paquet) :

    - make

    • mingw64-x86_64-gcc-core (uniquement nécessaire pour hsdis-amd64.dll )
    • mingw-gcc-core (uniquement nécessaire pour hsdis-i386.dll )
  2. 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).

  3. 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.

  4. Téléchargez le dernier paquetage source d'OpenJDK et extraire le hsdis (trouvé dans openjdk\hotspot\src\share\tools ) dans votre répertoire personnel Cygwin. Au moment où nous écrivons ces lignes, le dernier paquet est le suivant openjdk-7u6-fcs-src-b24-28_aug_2012.zip . Cela devrait donner lieu à un répertoire nommé hsdis dans votre répertoire personnel Cygwin.

  5. Dans le terminal Cygwin, entrez cd hsdis .

  6. Pour construire hsdis-amd64.dll Entrez make OS=Linux MINGW=x86_64-w64-mingw32 BINUTILS=~/binutils-2.23.1 . Pour construire hsdis-i386.dll , entrez < make OS=Linux MINGW=i686-pc-mingw32 BINUTILS=~/binutils-2.23.1 . Dans les deux cas, remplacez 2.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

46voto

Falaina Points 4760

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=#

29voto

swojtasiak Points 31

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

8voto

John Rose Points 61

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.

5voto

Andrey Tkach Points 1068

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
    et a obtenu

    00402f68 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.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X