Gibt es eine Möglichkeit, den vom JIT in einer JVM erzeugten nativen Code zu sehen?
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.
Wie in anderen Antworten erläutert, können Sie mit den folgenden JVM-Optionen ausgeführt werden:
-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly
Sie können auch nach einer bestimmten Methode mit der folgenden Syntax filtern:
-XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*MyClass.myMethod
Anmerkungen:
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.
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)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>\
).
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.src\share\tools
) in Ihr Cygwin-Home-Verzeichnis.cd ~/hsdis
ein.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.
./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
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:
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
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
/usr/lib/jvm/Java-8-Oracle
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
Für die HotSpot (war Sun) JVM, auch in Produktmodi:
http://wikis.Oracle.com/display/HotSpotInternals/PrintAssembly
Einige Montage erforderlich: Es braucht ein Plugin.
Ich glaube, WinDbg wäre hilfreich, wenn Sie es auf einem Windows-Rechner ausführen. Ich habe gerade ein Glas laufen lassen.
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.
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.
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.