Есть ли способ увидеть собственный код, созданный JIT в JVM?
Есть ли способ увидеть собственный код, созданный JIT в JVM?
Ответы:
Предполагая, что вы используете JVM Sun Hotspot (то есть ту, которая предоставляется Oracle на java.com ), вы можете добавить флаг
-XX: + PrintOptoAssembly
при запуске вашего кода. Это распечатает оптимизированный код, сгенерированный JIT-компилятором, и оставит все остальное.
Если вы хотите увидеть весь байт-код, включая неоптимизированные части, добавьте
-XX: CompileThreshold = #
когда вы запускаете свой код.
Вы можете узнать больше об этой команде и о функциональных возможностях JIT в целом здесь .
Как объясняется в других ответах, вы можете работать со следующими параметрами JVM:
-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly
Вы также можете отфильтровать определенный метод с помощью следующего синтаксиса:
-XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*MyClass.myMethod
Ноты:
Если вы используете Windows, на этой странице есть инструкции по сборке и установке, hsdis-amd64.dll
а также о том, hsdis-i386.dll
что необходимо для ее работы. Мы копируем ниже и расширяем содержание этой страницы * для справки:
Где взять готовые двоичные файлы
Вы можете скачать готовые двоичные файлы для Windows из проекта fcml
Как собрать hsdis-amd64.dll
и hsdis-i386.dll
на Windows
Эта версия руководства была подготовлена для 64-разрядной версии Windows 8.1 с использованием 64-разрядной версии Cygwin и создания hsdis-amd64.dll.
Установите Cygwin . На Select Packages
экране добавьте следующие пакеты (развернув Devel
категорию, а затем один раз щелкнув Skip
ярлык рядом с названием каждого пакета):
make
mingw64-x86_64-gcc-core
(требуется только для hsdis-amd64.dll
)mingw64-i686-gcc-core
(требуется только для hsdis-i386.dll
)diffutils
(в Utils
категории)Запустите терминал Cygwin. Это можно сделать с помощью значка на рабочем столе или в меню «Пуск», созданного установщиком, который создаст ваш домашний каталог Cygwin ( C:\cygwin\home\<username>\
или C:\cygwin64\home\<username>\
по умолчанию).
binutils-2.25.tar.bz2
. Это должно привести к созданию каталога с именем binutils-2.25
(или любой другой последней версии) в вашем домашнем каталоге Cygwin.src\share\tools
) в домашний каталог Cygwin.cd ~/hsdis
.Чтобы построить hsdis-amd64.dll
, введите
make OS=Linux MINGW=x86_64-w64-mingw32 'AR=$(MINGW)-ar' BINUTILS=~/binutils-2.25
Чтобы построить hsdis-i386.dll
, введите
make OS=Linux MINGW=i686-w64-mingw32 'AR=$(MINGW)-ar' BINUTILS=~/binutils-2.25
В любом случае замените 2.25
загруженной версией binutils. OS=Linux
необходимо, потому что, хотя Cygwin является Linux-подобной средой, make-файл hsdis не может распознать ее как таковую.
./chew: No such file or directory
и gcc: command not found
. <Cygwin home directory>\hsdis\build\Linux-amd64\bfd\Makefile
В текстовом редакторе, таком как Wordpad или Notepad ++, отредактируйте SUBDIRS = doc po
(строка 342, если используется binutils 2.25) на SUBDIRS = po
. Повторите предыдущую команду.Теперь DLL можно установить, скопировав ее из hsdis\build\Linux-amd64
или hsdis\build\Linux-i586
в каталог JRE bin\server
или bin\client
. Вы можете найти все такие каталоги в своей системе, выполнив поиск java.dll
.
Дополнительный совет: если вы предпочитаете синтаксис Intel ASM -XX:PrintAssemblyOptions=intel
вместо AT&T, укажите вместе с любыми другими используемыми вами параметрами PrintAssembly.
* лицензия на страницу - Creative Commons
/usr/lib/
Для использования вам понадобится плагин hsdis PrintAssembly
. Удобный выбор - плагин hsdis на основе библиотеки FCML.
Его можно скомпилировать для UNIX-подобных систем, а в Windows вы можете использовать готовые библиотеки, доступные в разделе загрузки FCML на Sourceforge:
java.dll
(используйте поиск Windows). В своей системе я нашел его в двух местах:
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
Дополнительные параметры конфигурации:
code Вывести машинный код перед мнемоникой.
intel Используйте синтаксис Intel.
gas Используйте синтаксис ассемблера AT&T (совместимый с GNU ассемблер).
dec Печатает IMM и смещение как десятичные значения.
mpad = XX Заполнение мнемонической части инструкции.
cpad = XX Заполнение машинного кода.
seg Показывает регистры сегментов по умолчанию.
нули Показывать ведущие нули в случае шестнадцатеричных литералов.
Синтаксис Intel является синтаксисом по умолчанию в случае Windows, тогда как синтаксис AT&T используется по умолчанию для GNU / Linux.
Дополнительные сведения см. В Справочном руководстве по библиотеке FCML.
apt-get install libhsdis0-fcml
( askubuntu.com/a/991166/489909 ). Самостоятельное создание этого может не потребоваться.
Для JVM HotSpot (было Sun) даже в режимах продукта:
http://wikis.oracle.com/display/HotSpotInternals/PrintAssembly
Требуется некоторая сборка: нужен плагин.
Я считаю, что WinDbg будет полезен, если вы используете его на машине с Windows. Я только что запустил одну банку.
Просмотрел неуправляемый стек вызовов по 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
Выделенные строки - это прямой запуск JIT-кода на JVM.
Затем мы можем найти адрес метода:
java + 0x2f68 - 00402f68
В WinDBG:
нажмите «Просмотр» -> «Разборка».
Щелкните Правка -> Перейти к адресу.
Поставил туда 00402f68
и получил
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
... и так далее
Для получения дополнительной информации вот пример того, как отследить JIT-код из дампов памяти с помощью проводника процессов и WinDbg.
Распечатайте сборку ваших горячих точек с помощью профилировщика JMH perfasm ( LinuxPerfAsmProfiler
или WinPerfAsmProfiler
). JMH действительно требует hsdis
библиотеки, поскольку он полагается на PrintAssembly
.