Is there some way to see the native code produces by the JIT in a JVM?
-
Are you sure you want to see the JIT-compiled (native) code, or just the byte-code? I ask because asking this question here leads to some doubts if you really want to see native code... And, sorry, I don't know such a tool either. – gimpf Oct 01 '09 at 11:49
-
3I want to see exaclty JIT-compiled native code. Of course it is not something that I need to get job done, rather kind of experiments and investigating things. – alsor.net Oct 01 '09 at 12:03
-
Minor frame challenge: a dynamic compiler as used in modern JVMs doesn't have just _one_ version of compiled code; it may start off interpreting, then compile a method or just part of it, then potentially recompile it multiple times as classes get loaded/unloaded or usage patterns shift or based on performance stats. (I think it can even discard the compiled version and return to interpreting if that seems beneficial.) So you might not only get different code on different machines, nor even for different runs on the same machine, but at different times in the _same_ run. – gidds Jul 05 '20 at 13:07
7 Answers
General usage
As explained by other answers, you can run with the following JVM options:
-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly
Filter on a specific method
You can also filter on a specific method with the following 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 instructions on how to build and install hsdis-amd64.dll
and hsdis-i386.dll
which are required to make it work. We copy below and extend the content of that page* for reference:
Where to get prebuilt binaries
You can download prebuilt 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
Install Cygwin. At the
Select Packages
screen, add the following packages (by expanding theDevel
category, then clicking once on theSkip
label next to each package name):make
mingw64-x86_64-gcc-core
(only needed forhsdis-amd64.dll
)mingw64-i686-gcc-core
(only needed forhsdis-i386.dll
)diffutils
(inUtils
category)
Run the Cygwin Terminal. This can be done using the Desktop or Start Menu icon created by the installer, and will create your Cygwin home directory (
C:\cygwin\home\<username>\
orC:\cygwin64\home\<username>\
by default).- 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 namedbinutils-2.25
(or whatever the latest version is) in your Cygwin home directory. - 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. - In the Cygwin Terminal, enter
cd ~/hsdis
. To build
hsdis-amd64.dll
, entermake OS=Linux MINGW=x86_64-w64-mingw32 'AR=$(MINGW)-ar' BINUTILS=~/binutils-2.25
To build
hsdis-i386.dll
, entermake OS=Linux MINGW=i686-w64-mingw32 'AR=$(MINGW)-ar' BINUTILS=~/binutils-2.25
In either case, replace
2.25
with the binutils version you downloaded.OS=Linux
is necessary because, although Cygwin is a Linux-like environment, the hsdis makefile fails to recognize it as such.- The build will fail with messages
./chew: No such file or directory
andgcc: command not found
. Edit<Cygwin home directory>\hsdis\build\Linux-amd64\bfd\Makefile
in a text editor like Wordpad or Notepad++ to changeSUBDIRS = doc po
(line 342, if using binutils 2.25) toSUBDIRS = po
. Re-run the previous command.
The DLL can now be installed by copying it from hsdis\build\Linux-amd64
or hsdis\build\Linux-i586
to your JRE's bin\server
or bin\client
directory. You can find all such directories on your system by searching for java.dll
.
Bonus tip: if you prefer Intel ASM syntax to AT&T, specify -XX:PrintAssemblyOptions=intel
alongside any other PrintAssembly options you use.
*page license is Creative Commons

- 321,522
- 82
- 660
- 783
-
1Pre-built binaries for other platforms - https://kenai.com/projects/base-hsdis/downloads – Ashwin Jayaprakash Oct 28 '13 at 17:23
-
@AshwinJayaprakash Where am I supposed to put these files in Mac OS? – Koray Tugay Jan 24 '15 at 12:53
-
-
I've updated the answer by copying from the latest version of the linked-to page, but this highlights the reason we generally link to external resources rather than copy them verbatim. – Aleksandr Dubinsky May 23 '15 at 19:39
-
@AleksandrDubinsky Thanks for the update. I copied it on purpose: if that site is brought down my answer will still be self contained... – assylias May 23 '15 at 19:43
-
FYI, do NOT use this other guide jpbempel.blogspot.com/2013/07/how-to-build-hsdis-amd64dll.html to try to build `hsdis` using MSYS/MinGW. It doesn't work. – Aleksandr Dubinsky May 24 '15 at 00:20
Assuming you're using the Sun Hotspot JVM (i.e. the one provided on java.com by Oracle), you can add the flag
-XX:+PrintOptoAssembly
when running your code. This will print out the optimized code generated by the JIT compiler and leaves out the rest.
If you want see the entire bytecode, including the unoptimized parts, add
-XX:CompileThreshold=#
when you're running your code.
You can read more about this command and the functionality of JIT in general here.
-
Is this option only present in debug builds or anything? Because my JVM ("Java(TM) SE Runtime Environment (build 1.6.0_16-b01") doesn't recognize it even though source on the web indicate this feature being available in Sun Java 6 and OpenJDK. – Joachim Sauer Oct 01 '09 at 13:27
-
2Yes, DEBUG binaries needed. http://blogs.warwick.ac.uk/richardwarburton/entry/hotspot_print_assembly/ – alsor.net Oct 01 '09 at 13:41
-
3Shouldn't that be (nowadays) -XX:+PrintAssembly, at least nowadays? Tested on my machine, and matches what is said here: http://wikis.sun.com/display/HotSpotInternals/PrintAssembly You need -XX:+UnlockDiagnosticVMOptions before this option and a disassembler plugin. – Blaisorblade Nov 22 '11 at 13:40
-
@Blaisorblade I am getting: Improperly specified VM option 'PrintAssembly' Error: Could not create the Java Virtual Machine. Error: A fatal exception has occurred. Program will exit. – Koray Tugay Jan 24 '15 at 12:42
-
1@KorayTugay See other answers — the updated link is https://wikis.oracle.com/display/HotSpotInternals/PrintAssembly, as given in http://stackoverflow.com/a/15146962/53974 or http://stackoverflow.com/a/4149878/53974. If following instructions doesn't work, please ask with details at some appropriate place (not sure whether it should another question for your case, referencing this one). – Blaisorblade Feb 13 '15 at 19:21
You need an hsdis plugin to use PrintAssembly
. A convenient choice is the hsdis plugin based on FCML library.
It can be compiled for UNIX-like systems and on Windows you can use pre-built libraries available in the FCML download section 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 parameters:
code Print machine code before the mnemonic.
intel Use the Intel syntax.
gas Use the AT&T assembler syntax (GNU assembler compatible).
dec Prints IMM and displacement as decimal values.
mpad=XX Padding for the mnemonic part of the instruction.
cpad=XX Padding for the machine code.
seg Shows the default segment registers.
zeros Show leading zeros in case of HEX literals.
The Intel syntax is a default one in case of Windows, whereas the AT&T one is a default for the GNU/Linux.
For more details see the FCML Library Reference Manual

- 606
- 6
- 12
-
Thanks for fixing the lib. It's working great on Linux as well. I'm deleting my old comments to keep clutter down. – Aleksandr Dubinsky Oct 01 '15 at 15:39
-
On Linux, after I install the libhsdis.so and make a soft link to hsdis-amd64.so, I run the java command, it prmpts can't find the hsdis-amd64.so. I reboot and then rerun java, it's ok. How to avoid reboot to make the soft link work instantly? logout? – gfan Apr 06 '17 at 08:47
-
2Just a little addition: On some linux distributions, you can just install a package, for example in Ubuntu: `apt-get install libhsdis0-fcml` (https://askubuntu.com/a/991166/489909). Building this yourself may not be necessary. – David Georg Reichelt Jun 03 '19 at 15:43
For the HotSpot (was Sun) JVM, even in product modes:
http://wikis.oracle.com/display/HotSpotInternals/PrintAssembly
Some assembly required: it needs a plugin.
-
It seems that the link in your answer is gone.Would you please update it?Thanks in advance. – lin May 11 '17 at 06:31
I believe WinDbg would be helpful if you are running it on windows machine. I have 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 callstack by kb there was:
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
Highlighted lines is direct running JIT-ed code on JVM.
Then we can look for method address:
java+0x2f68 is 00402f68On WinDBG:
Click View --> Disassembly.
Click Edit --> Go to Address.
Put 00402f68 there
and got00402f68 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
... and so on
For additional info here is the Example how to trace back JIT-ed code from memory dumps using process explorer and WinDbg.

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

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

- 22,436
- 15
- 82
- 99