[ACCEPTED]-How to see JIT-compiled code in JVM?-jit

Accepted answer
Score: 81

General usage

As explained by other answers, you can run 26 with the following JVM options:

-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly

Filter on a specific method

You can also 25 filter on a specific method with the following 24 syntax:

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

Notes:

  • you might need to put the second argument within quotes depending on OS etc.
  • if the method gets inlined, you could miss some optimisations

How to: Install the required libraries on Windows

If you are running Windows, this page has 23 instructions on how to build and install 22 hsdis-amd64.dll and hsdis-i386.dll which are required to make it work. We 21 copy below and extend the content of that 20 page* for reference:


Where to get prebuilt binaries

You can download prebuilt 19 binaries for Windows from the fcml project

How to build hsdis-amd64.dll and hsdis-i386.dll on Windows

This version of the guide was prepared on Windows 8.1 64bit using 64-bit Cygwin and producing hsdis-amd64.dll

  1. Install Cygwin. At 18 the Select Packages screen, add the following packages 17 (by expanding the Devel category, then clicking 16 once on the Skip label next to each package 15 name):

    • make
    • mingw64-x86_64-gcc-core (only needed for hsdis-amd64.dll)
    • mingw64-i686-gcc-core (only needed for hsdis-i386.dll)
    • diffutils (in Utils category)
  2. Run the Cygwin Terminal. This can 14 be done using the Desktop or Start Menu 13 icon created by the installer, and will 12 create your Cygwin home directory (C:\cygwin\home\<username>\ or C:\cygwin64\home\<username>\ by 11 default).

  3. Download the latest GNU binutils source package and extract its contents to your Cygwin home directory. At the time of writing, the latest package is binutils-2.25.tar.bz2. This should result in a directory named binutils-2.25 (or whatever the latest version is) in your Cygwin home directory.
  4. Download the OpenJDK source by going to the JDK 8 Updates repository, selecting the tag corresponding to your installed JRE version, and clicking bz2. Extract the hsdis directory (found in src\share\tools) to your Cygwin home directory.
  5. In the Cygwin Terminal, enter cd ~/hsdis.
  6. To build hsdis-amd64.dll, enter

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

    To build hsdis-i386.dll, enter 10

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

    In either case, replace 2.25 with the binutils 9 version you downloaded. OS=Linux is necessary because, although 8 Cygwin is a Linux-like environment, the 7 hsdis makefile fails to recognize it as 6 such.

  7. The build will fail with messages ./chew: No such file or directory and gcc: command not found. Edit <Cygwin home directory>\hsdis\build\Linux-amd64\bfd\Makefile in a text editor like Wordpad or Notepad++ to change SUBDIRS = doc po (line 342, if using binutils 2.25) to SUBDIRS = po. Re-run the previous command.

The DLL can now be installed by copying 5 it from hsdis\build\Linux-amd64 or hsdis\build\Linux-i586 to your JRE's bin\server or bin\client directory. You 4 can find all such directories on your system 3 by searching for java.dll.

Bonus tip: if you prefer 2 Intel ASM syntax to AT&T, specify -XX:PrintAssemblyOptions=intel alongside 1 any other PrintAssembly options you use.

*page license is Creative Commons

Score: 46

Assuming you're using the Sun Hotspot JVM 10 (i.e. the one provided on java.com by Oracle), you 9 can add the flag

-XX:+PrintOptoAssembly

when 8 running your code. This will print out the 7 optimized code generated by the JIT compiler 6 and leaves out the rest.

If you want see 5 the entire bytecode, including the unoptimized 4 parts, add

-XX:CompileThreshold=#

when you're 3 running your code.

You can read more about 2 this command and the functionality of JIT 1 in general here.

Score: 29

You need an hsdis plugin to use PrintAssembly. A convenient 17 choice is the hsdis plugin based on FCML 16 library.

It can be compiled for UNIX-like 15 systems and on Windows you can use pre-built 14 libraries available in the FCML download section 13 on Sourceforge:

To install in Windows:

  • Extract the dll (it can be found in hsdis-1.1.2-win32-i386.zip and hsdis-1.1.2-win32-amd64.zip).
  • Copy the dll to wherever exists java.dll (use Windows search). On my system, I found it at two locations:
    • C:\Program Files\Java\jre1.8.0_45\bin\server
    • C:\Program Files\Java\jdk1.8.0_45\jre\bin\server

To install in Linux:

  • Download source code, extract it
  • 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
  • On my system, the JDK is in /usr/lib/jvm/java-8-oracle

How to run it:

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

Additional configuration 12 parameters:

code Print machine code before the 11 mnemonic.
intel Use the Intel syntax.
gas Use the 10 AT&T assembler syntax (GNU assembler 9 compatible).
dec Prints IMM and displacement 8 as decimal values.
mpad=XX Padding for the mnemonic 7 part of the instruction.
cpad=XX Padding for the 6 machine code.
seg Shows the default segment 5 registers.
zeros Show leading zeros in case of 4 HEX literals.

The Intel syntax is a default 3 one in case of Windows, whereas the AT&T 2 one is a default for the GNU/Linux.

For more 1 details see the FCML Library Reference Manual

Score: 8

For the HotSpot (was Sun) JVM, even in product 2 modes:

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

Some assembly required: it needs 1 a plugin.

Score: 5

I believe WinDbg would be helpful if you 20 are running it on windows machine. I have 19 just run one jar.

  • Then I attached to the java process through Windbg
  • Examined threads by ~ command; There were 11 threads, 0 thread was main worker thread
  • Switched to 0-thread - ~0s
  • Looked through unmanmaged 18 callstack by kb there was:

    0008fba8 7c90e9c0 17 ntdll!KiFastSystemCallRet
    0008fbac 7c8025cb 16 ntdll!ZwWaitForSingleObject+0xc
    0008fc10 15 7c802532 kernel32!WaitForSingleObjectEx+0xa8
    0008fc24 14 00403a13 kernel32!WaitForSingleObject+0x12
    0008fc40 00402f68 java+0x3a13
    0008fee4 004087b8 java+0x2f68
    0008ffc0 7c816fd7 java+0x87b8

    0008fff0 13 00000000 kernel32!BaseProcessStart+0x23

Highlighted 12 lines is direct running JIT-ed code on JVM.

  • Then 11 we can look for method address:
    java+0x2f68 is 00402f68

  • On WinDBG:
    Click 10 View --> Disassembly.
    Click Edit --> Go 9 to Address.
    Put 00402f68 there
    and got

    00402f68 8 55 push ebp
    00402f69 8bec 7 mov ebp,esp
    00402f6b 81ec80020000 6 sub esp,280h
    00402f71 53 push 5 ebx
    00402f72 56 push esi
    00402f73 4 57 push edi
    ... and so on

For 3 additional info here is the Example how to trace 2 back JIT-ed code from memory dumps using 1 process explorer and WinDbg.

Score: 4

Another way to see machine code and some 4 performance data is to use AMD's CodeAnalyst 3 or OProfile, which have a Java plugin to 2 visualize executing Java code as machine 1 code.

Score: 1

Print the assembly of your hotspots with 3 JMH's perfasm profilers (LinuxPerfAsmProfiler or WinPerfAsmProfiler). JMH does 2 require the hsdis library since it relies on 1 PrintAssembly.

More Related questions