JVMでJITによって生成されたネイティブコードを確認する方法はありますか?
JVMでJITによって生成されたネイティブコードを確認する方法はありますか?
回答:
Sun Hotspot JVM(つまり、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
それを機能させるために必要な手順が記載されています。以下をコピーし、参照用にそのページ*のコンテンツを拡張します。
ビルド済みのバイナリを入手する場所
fcmlプロジェクトからWindows用のビルド済みバイナリをダウンロードできます
どのように構築するhsdis-amd64.dll
と、hsdis-i386.dll
Windows上で
このバージョンのガイドは、64ビットのCygwinを使用し、hsdis-amd64.dllを生成するWindows 8.164ビットで作成されました。
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に似た環境ですが、hsdismakefileはそれをそのように認識できないために必要です。
./chew: No such file or directory
とで失敗しますgcc: command not found
。<Cygwin home directory>\hsdis\build\Linux-amd64\bfd\Makefile
WordpadやNotepad ++などのテキストエディタで編集してSUBDIRS = doc po
(binutils 2.25を使用している場合は342行目)をに変更しSUBDIRS = po
ます。前のコマンドを再実行してください。DLLは、今からそれをコピーしてインストールすることができるhsdis\build\Linux-amd64
か、hsdis\build\Linux-i586
あなたのJREのにbin\server
またはbin\client
ディレクトリ。を検索すると、システム上のそのようなディレクトリをすべて見つけることができますjava.dll
。
ボーナスのヒント:AT&TよりもIntel ASM構文を-XX:PrintAssemblyOptions=intel
使用する場合は、使用する他のPrintAssemblyオプションと一緒に指定してください。
*ページライセンスはクリエイティブコモンズです
/usr/lib/
を使用するには、hsdisプラグインが必要PrintAssembly
です。便利な選択は、FCMLライブラリに基づくhsdisプラグインです。
UNIXライクなシステム用にコンパイルでき、WindowsではSourceforgeのFCMLダウンロードセクションにあるビルド済みライブラリを使用できます。
java.dll
(Windowsサーチを使用)。私のシステムでは、次の2つの場所で見つかりました。
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ニーモニックの前にマシンコードを印刷します。
intelIntel構文を使用します。
gas AT&Tアセンブラ構文(GNUアセンブラ互換)を使用します。
12月プリントIMMと小数点値として変位。
mpad = XX命令のニーモニック部分のパディング。
cpad = XXマシンコードのパディング。
segデフォルトのセグメントレジスタを表示します。
ゼロHEXリテラルの場合、先行ゼロを表示します。
Windowsの場合はIntel構文がデフォルトですが、GNU / Linuxの場合はAT&T構文がデフォルトです。
詳細については、FCMLライブラリリファレンスマニュアルを参照してください。
apt-get install libhsdis0-fcml
(askubuntu.com/a/991166/489909)。これを自分で作成する必要はないかもしれません。
HotSpot(以前はSun)JVMの場合、製品モードでも次のようになります。
http://wikis.oracle.com/display/HotSpotInternals/PrintAssembly
いくつかのアセンブリが必要です:プラグインが必要です。
WinDbgは、Windowsマシンで実行している場合に役立つと思います。私はちょうど1つの瓶を実行しました。
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
強調表示されている行は、JVMで直接実行されているJITコードです。
次に、メソッドアドレスを探すことができます
。java+ 0x2f68は00402f68です。
WinDBGの場合:
[表示]-> [逆アセンブリ]をクリックします。
[編集]-> [アドレスに移動]をクリックします。
入れ00402f68そこ
とGOT
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
...など
追加情報については、ProcessExplorerとWinDbgを使用してメモリダンプからJITされたコードをトレースバックする方法の例を示します。
JMHのパフォーマンスプロファイラー(LinuxPerfAsmProfiler
またはWinPerfAsmProfiler
)を使用して、ホットスポットのアセンブリを印刷します。JMHはhsdis
に依存しているため、ライブラリは必要ですPrintAssembly
。