web-dev-qa-db-de.com

Wie wird JIT-kompilierter Code in JVM angezeigt?

Gibt es eine Möglichkeit, den vom JIT in einer JVM erzeugten nativen Code zu sehen?

69
alsor.net

Wenn Sie die Sun Hotspot-JVM verwenden (d. H. Die von Java.com von Oracle bereitgestellte), können Sie das Flag hinzufügen

-XX: + PrintOptoAssembly

wenn Sie Ihren Code ausführen. Dadurch wird der vom JIT-Compiler generierte optimierte Code ausgedruckt und der Rest wird ausgelassen.

Wenn Sie den gesamten Bytecode einschließlich der nicht optimierten Teile sehen möchten, fügen Sie hinzu

-XX: CompileThreshold = #

wenn Sie Ihren Code ausführen.

Mehr über diesen Befehl und die Funktionalität von JIT im Allgemeinen hier können Sie lesen.

39
Falaina

Allgemeine Verwendung

Wie in anderen Antworten erläutert, können Sie mit den folgenden JVM-Optionen ausgeführt werden:

-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly

Filtern Sie nach einer bestimmten Methode

Sie können auch nach einer bestimmten Methode mit der folgenden Syntax filtern:

-XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*MyClass.myMethod

Anmerkungen:

  • sie müssen möglicherweise das zweite Argument in Anführungszeichen setzen, je nach Betriebssystem usw.
  • wenn die Methode eingebettet wird, könnten Sie einige Optimierungen verpassen

Vorgehensweise: Installieren Sie die erforderlichen Bibliotheken unter Windows

Wenn Sie Windows ausführen, enthält diese Seite Anweisungen zum Erstellen und Installieren von hsdis-AMD64.dll und hsdis-i386.dll, die erforderlich sind, damit es funktioniert. Wir kopieren unten und erweitern den Inhalt dieser Seite * als Referenz:


Wo bekomme ich vorgefertigte Binärdateien

Sie können vorgefertigte Binärdateien für Windows vom Projekt fcml herunterladen

Wie man hsdis-AMD64.dll und hsdis-i386.dll unter Windows erstellt

Diese Version des Handbuchs wurde unter Windows 8.1 64bit mit 64-Bit-Cygwin erstellt und erstellt hsdis-AMD64.dll.

  1. Cygwin installieren . Fügen Sie im Bildschirm Select Packages die folgenden Pakete hinzu (erweitern Sie die Kategorie Devel und klicken Sie einmal auf das Label Skip neben jedem Paketnamen):

    • make
    • mingw64-x86_64-gcc-core (wird nur für hsdis-AMD64.dll benötigt)
    • mingw64-i686-gcc-core (wird nur für hsdis-i386.dll benötigt)
    • diffutils (in der Utils-Kategorie)
  2. Führen Sie das Cygwin-Terminal aus. Dies kann über das Desktop- oder Startmenüsymbol erfolgen, das vom Installationsprogramm erstellt wurde, und erstellt ein Cygwin-Home-Verzeichnis (standardmäßig C:\cygwin\home\<username>\ oder C:\cygwin64\home\<username>\).

  3. Laden Sie das neueste GNU binutils-Quellpaket herunter und extrahieren Sie den Inhalt in Ihr Cygwin-Home-Verzeichnis. Zum Zeitpunkt des Schreibens ist das neueste Paket binutils-2.25.tar.bz2. Dies sollte zu einem Verzeichnis mit dem Namen binutils-2.25 (oder der aktuellsten Version) in Ihrem Cygwin-Ausgangsverzeichnis führen.
  4. Laden Sie die OpenJDK-Quelle herunter, indem Sie zum Repository für JDK 8-Updates gehen , das Tag auswählen, das Ihrer installierten JRE-Version entspricht, und auf bz2 klicken. Extrahieren Sie das hsdis-Verzeichnis (gefunden in src\share\tools) in Ihr Cygwin-Home-Verzeichnis.
  5. Geben Sie im Cygwin-Terminal cd ~/hsdis ein.
  6. Um hsdis-AMD64.dll zu erstellen, geben Sie ein 

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

    Um hsdis-i386.dll zu erstellen, geben Sie ein 

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

    Ersetzen Sie in beiden Fällen 2.25 durch die heruntergeladene binutils-Version. OS=Linux ist notwendig, da Cygwin zwar eine Linux-ähnliche Umgebung ist, das hsdis-Makefile es jedoch nicht als solches erkennt.

  7. Der Build schlägt mit den Nachrichten ./chew: No such file or directory und gcc: command not found fehl. Bearbeiten Sie <Cygwin home directory>\hsdis\build\Linux-AMD64\bfd\Makefile in einem Texteditor wie Wordpad oder Notepad ++, um SUBDIRS = doc po (Zeile 342, wenn Sie binutils 2.25 verwenden) in SUBDIRS = po zu ändern. Führen Sie den vorherigen Befehl erneut aus.

Das DLL kann jetzt installiert werden, indem Sie es aus hsdis\build\Linux-AMD64 oder hsdis\build\Linux-i586 in das Verzeichnis bin\server oder bin\client Ihrer JRE kopieren. Sie finden alle diese Verzeichnisse in Ihrem System, indem Sie nach Java.dll suchen.

Bonus-Tipp: Wenn Sie die Intel ASM-Syntax gegenüber AT & T bevorzugen, geben Sie -XX:PrintAssemblyOptions=intel neben allen anderen von Ihnen verwendeten PrintAssembly-Optionen an.

* Seitenlizenz ist Creative Commons

65
assylias

Sie benötigen ein hsdis-Plugin, um PrintAssembly verwenden zu können. Eine bequeme Wahl ist das hsdis-Plugin, das auf der FCML-Bibliothek basiert.

Es kann für UNIX-ähnliche Systeme kompiliert werden und unter Windows können Sie vordefinierte Bibliotheken verwenden, die im Abschnitt FCML download von Sourceforge verfügbar sind:

Installation unter Windows:

  • Extrahieren Sie die DLL (sie kann in hsdis-1.1.2-win32-i386.Zip und hsdis-1.1.2-win32-AMD64.Zip gefunden werden).
  • Kopieren Sie die DLL in das Verzeichnis Java.dll (verwenden Sie die Windows-Suche). Auf meinem System habe ich es an zwei Stellen gefunden:
    • C:\Program Files\Java\jre1.8.0_45\bin\server
    • C:\Program Files\Java\jdk1.8.0_45\jre\bin\server

Installation unter Linux:

  • Quellcode herunterladen, entpacken
  • 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
  • Auf meinem System befindet sich das JDK in /usr/lib/jvm/Java-8-Oracle

Wie man es ausführt:

Java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly 
-XX:+LogCompilation -XX:PrintAssemblyOptions=intel,mpad=10,cpad=10,code 
-jar fcml-test.jar

Zusätzliche Konfigurationsparameter:

code Maschinencode vor der Mnemonik drucken.
intel Verwenden Sie die Intel-Syntax.
gas Verwenden Sie die AT & T-Assemblersyntax (kompatibel mit GNU-Assembler).
dez Druckt IMM und Verschiebung als Dezimalwerte.
mpad = XX Auffüllung für den mnemonischen Teil der Anweisung.
cpad = XX Auffüllung für den Maschinencode.
seg Zeigt die Standard-Segmentregister.
nullen Bei HEX-Literalen führende Nullen anzeigen.

Die Intel-Syntax ist eine Standardeinstellung für Windows, während die AT & T-Syntax eine Standardeinstellung für GNU/Linux ist.

Weitere Informationen finden Sie im FCML Library Reference Manual

24
swojtasiak

Für die HotSpot (war Sun) JVM, auch in Produktmodi:

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

Einige Montage erforderlich: Es braucht ein Plugin.

8
John Rose

Ich glaube, WinDbg wäre hilfreich, wenn Sie es auf einem Windows-Rechner ausführen. Ich habe gerade ein Glas laufen lassen.

  • Dann habe ich an den Java-Prozess Durch Windbg angeschlossen.
  • Untersuchte Threads mit ~ command; Es gab 11 Threads, 0 Thread war Hauptarbeitsthread
  • Umgestellt auf 0-Thread - ~ 0s
  • Unmanmaged Callstack nach kb durchgesehen:

    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

Hervorgehobene Zeilen führen direkt JIT-ed-Code in der JVM aus.

  • Dann können wir nach der Adresse der Methode suchen:
    Java + 0x2f68 ist 00402f68

  • In WinDBG:
    Klicken Sie auf Ansicht -> Demontage.
    Klicken Sie auf Bearbeiten -> Gehe zu Adresse.
    Setzen Sie 00402f68 dort
    und bekam 

    00402f68 55 Drücken Sie die Taste ebp
    00402f69 8bec mov ebp, insb
    00402f6b 81ec80020000 sub esp, 280h
    00402f71 53 Drücken Sie die Taste ebx
    00402f72 56 Esi drücken
    00402f73 57 Push edi
    ... und so weiter

Weitere Informationen hierzu finden Sie im Beispiel , wie JIT-ed-Code aus Speicherabbildern mithilfe des Prozess-Explorers und WinDbg zurückverfolgt wird.

5
Andriy Tkach

Maschinencode und einige Leistungsdaten können Sie auch mit AMDs CodeAnalyst oder OProfile anzeigen, die über ein Java-Plugin verfügen, um die Ausführung von Java-Code als Maschinencode zu visualisieren.

4
Ian

Drucken Sie die Assembly Ihrer Hotspots mit den Perfasm-Profilern von JMH (LinuxPerfAsmProfiler oder WinPerfAsmProfiler). JMH benötigt die Bibliothek hsdis, da sie auf PrintAssembly angewiesen ist.

0