Czy istnieje sposób, aby zobaczyć natywny kod generowany przez JIT w JVM?
Czy istnieje sposób, aby zobaczyć natywny kod generowany przez JIT w JVM?
Odpowiedzi:
Zakładając, że używasz maszyny wirtualnej Sun Hotspot JVM (tj. Tej dostarczonej na java.com przez Oracle), możesz dodać flagę
-XX: + PrintOptoAssembly
podczas uruchamiania kodu. Spowoduje to wydrukowanie zoptymalizowanego kodu wygenerowanego przez kompilator JIT i pominie resztę.
Jeśli chcesz zobaczyć cały kod bajtowy, w tym niezoptymalizowane części, dodaj
-XX: CompileThreshold = #
kiedy uruchamiasz swój kod.
Możesz przeczytać więcej o tym poleceniu i ogólnie o funkcjonalności JIT tutaj .
Jak wyjaśniono w innych odpowiedziach, możesz uruchomić z następującymi opcjami JVM:
-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly
Możesz również filtrować według określonej metody za pomocą następującej składni:
-XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*MyClass.myMethod
Uwagi:
Jeśli używasz systemu Windows, na tej stronie znajdują się instrukcje, jak zbudować i zainstalować hsdis-amd64.dll
oraz hsdis-i386.dll
co jest wymagane, aby działał. Kopiujemy poniżej i rozszerzamy zawartość tej strony * w celach informacyjnych:
Skąd wziąć gotowe pliki binarne
Możesz pobrać gotowe pliki binarne dla systemu Windows z projektu fcml
Jak budować hsdis-amd64.dll
i hsdis-i386.dll
na Windowsie
Ta wersja poradnika została przygotowana na Windows 8.1 64-bitowym przy użyciu 64-bitowego Cygwin i produkując hsdis-amd64.dll
Zainstaluj Cygwin . Na Select Packages
ekranie dodaj następujące pakiety (rozwijając Devel
kategorię, a następnie klikając raz Skip
etykietę obok nazwy każdego pakietu):
make
mingw64-x86_64-gcc-core
(potrzebne tylko do hsdis-amd64.dll
)mingw64-i686-gcc-core
(potrzebne tylko do hsdis-i386.dll
)diffutils
(w Utils
kategorii)Uruchom terminal Cygwin. Można to zrobić za pomocą ikony Pulpit lub Menu Start utworzonej przez instalator i utworzy katalog domowy Cygwin ( C:\cygwin\home\<username>\
lub C:\cygwin64\home\<username>\
domyślnie).
binutils-2.25.tar.bz2
. Powinno to spowodować utworzenie katalogu o nazwie binutils-2.25
(lub jakiejkolwiek najnowszej wersji) w katalogu domowym Cygwin.src\share\tools
) do katalogu domowego Cygwin.cd ~/hsdis
.Aby zbudować hsdis-amd64.dll
, wejdź
make OS=Linux MINGW=x86_64-w64-mingw32 'AR=$(MINGW)-ar' BINUTILS=~/binutils-2.25
Aby zbudować hsdis-i386.dll
, wejdź
make OS=Linux MINGW=i686-w64-mingw32 'AR=$(MINGW)-ar' BINUTILS=~/binutils-2.25
W obu przypadkach zastąp 2.25
pobraną wersją binutils. OS=Linux
jest konieczne, ponieważ chociaż Cygwin jest środowiskiem podobnym do Linuksa, plik makefile hsdis nie rozpoznaje go jako takiego.
./chew: No such file or directory
i gcc: command not found
. Edytuj <Cygwin home directory>\hsdis\build\Linux-amd64\bfd\Makefile
w edytorze tekstu, takim jak Wordpad lub Notepad ++, aby zmienić SUBDIRS = doc po
(wiersz 342, jeśli używasz binutils 2.25) na SUBDIRS = po
. Ponownie uruchom poprzednie polecenie.Bibliotekę DLL można teraz zainstalować, kopiując ją z hsdis\build\Linux-amd64
lub hsdis\build\Linux-i586
do środowiska JRE bin\server
lub bin\client
katalogu. Możesz znaleźć wszystkie takie katalogi w swoim systemie, wyszukując java.dll
.
Dodatkowa wskazówka: jeśli wolisz składnię Intel ASM od AT&T, określ -XX:PrintAssemblyOptions=intel
obok innych używanych opcji PrintAssembly.
* Licencja strony to Creative Commons
/usr/lib/
Potrzebujesz wtyczki hsdis do użycia PrintAssembly
. Wygodnym wyborem jest wtyczka hsdis oparta na bibliotece FCML.
Można go skompilować dla systemów typu UNIX, aw systemie Windows można użyć gotowych bibliotek dostępnych w sekcji pobierania FCML na Sourceforge:
java.dll
(użyj wyszukiwania systemu Windows). W moim systemie znalazłem go w dwóch lokalizacjach:
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
Dodatkowe parametry konfiguracyjne:
kod Wydrukuj kod maszynowy przed mnemonikiem.
intel Użyj składni Intela.
gas Używa składni asemblera AT&T (kompatybilna z GNU assembler).
dec Drukuje IMM i przemieszczenie jako wartości dziesiętne.
mpad = XX Wypełnienie mnemonicznej części instrukcji.
cpad = XX Wypełnienie kodu maszynowego.
seg Pokazuje domyślne rejestry segmentów.
zera W przypadku literałów szesnastkowych wyświetla zera wiodące.
Składnia Intela jest domyślna w przypadku Windows, podczas gdy AT&T jest domyślna dla GNU / Linux.
Aby uzyskać więcej informacji, zobacz Podręcznik referencyjny biblioteki FCML
apt-get install libhsdis0-fcml
( askubuntu.com/a/991166/489909 ). Samodzielne budowanie może nie być konieczne.
W przypadku HotSpot (wcześniej Sun) JVM, nawet w trybach produktu:
http://wikis.oracle.com/display/HotSpotInternals/PrintAssembly
Wymagany montaż: wymaga wtyczki.
Wierzę, że WinDbg byłby pomocny, jeśli uruchamiasz go na komputerze z systemem Windows. Właśnie wypuściłem jeden słoik.
Przejrzałem niezarządzany stos wywołań przez kb :
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
Wyróżnione wiersze to bezpośrednio uruchamiany kod JIT w JVM.
Następnie możemy poszukać adresu metody:
java + 0x2f68 to 00402f68
W WinDBG:
Kliknij Widok -> Demontaż.
Kliknij Edytuj -> Idź do adresu.
Umieść 00402f68 tam
i otrzymaj
00402f68 55 push ebp
00402f69 8bec mov ebp, esp
00402f6b 81ec80020000 sub esp, 280h
00402f71 53 push ebx
00402f72 56 push esi
00402f73 57 push edi
... i tak dalej
Aby uzyskać dodatkowe informacje, tutaj znajduje się przykład śledzenia wstecznego kodu w formacie JIT ze zrzutów pamięci za pomocą eksploratora procesów i WinDbg.
Wydrukuj zespół swoich punktów aktywnych za pomocą profilerów perfasm JMH ( LinuxPerfAsmProfiler
lub WinPerfAsmProfiler
). JMH wymaga hsdis
biblioteki, ponieważ opiera się na PrintAssembly
.