Thankfully, the JVM abstracts all of the nitty gritty details from us. Sometimes though, we need to peel off the first layers and see what’s going on underneath. If you are curious (and here may be dragons) and want to learn about the actual assembler that your code is generating, the JVM provides mechanisms to inspect it.

Since I wanted to make it work on my development machine and didn’t find something comprehensive for Mac, here is how to do it.

First, make sure to have a more or less recent JDK installed. Mac ships with Java 6, but I think you want to upgrade to 7. You can grab the JDK packages from here if you haven’t already.

~ $ java -version java version "1.7.0_17" Java(TM) SE Runtime Environment (build 1.7.0_17-b02) Java HotSpot(TM) 64-Bit Server VM (build 23.7-b01, mixed mode)

Now to enable the ASM output, you need to pass in two flags, namely UnlockDiagnosticVMOptions and PrintAssembly . Because the generated ASM is different for each runtime, you need to pass it to the java command and not javac .

Create a very simple script like this and name it Main.java :

public class Main { public static void main(String[] args) { System.out.println("Hello World"); } }

Now, we’re going to compile and run it with those options:

[email protected] ~/Downloads/java $ javac Main.java && java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly Main Java HotSpot(TM) 64-Bit Server VM warning: PrintAssembly is enabled; turning on DebugNonSafepoints to gain additional output Could not load hsdis-amd64.dylib; library not loadable; PrintAssembly is disabled Hello World

Woops, not what we expected. The code did compile properly, but HotSpot complains about hsdis-amd64.dylib . I had to google a bit to find it, but you can download the file from here.

Now we need to put it somewhere to make it loadable, and the easiest thing I found is to put it onto LD_LIBRARY_PATH . Make sure to not override any other settings, but in my case the variable was empty so its straightforward.

export LD_LIBRARY_PATH=~/PathToFile/

If you run our command again from before, you should now see “beautiful” ASM code generated:

[email protected] ~/Downloads/java $ javac Main.java && java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly Main Java HotSpot(TM) 64-Bit Server VM warning: PrintAssembly is enabled; turning on DebugNonSafepoints to gain additional output Loaded disassembler from hsdis-amd64.dylib Decoding compiled method 0x000000010ac74150: 0x000000010ac742ba: add [eax], al [Disassembling for mach='i386(base-hsdis)'] [Entry Point] [Constants] # {method} 'hashCode' '()I' in 'java/lang/String' # [sp+0x30] (sp of caller) 0x000000010ac742a0: inc esp 0x000000010ac742a1: mov edx, [esi+0x8] 0x000000010ac742a4: dec ecx 0x000000010ac742a5: shl edx, 3 0x000000010ac742a8: dec ecx 0x000000010ac742a9: cmp eax, edx 0x000000010ac742ab: jnz 0x000000000ac4ba60 ; {runtime_call} 0x000000010ac742b1: nop 0x000000010ac742b4: invalid 0x0f #size=0 0x000000010ac742b5: pop ds 0x000000010ac742b6: test [eax], al 0x000000010ac742b8: add [eax], al 0x000000010ac742ba: add [eax], al 0x000000010ac742bc: nop [Verified Entry Point] 0x000000010ac742c0: mov [esp-0x14000], eax 0x000000010ac742c7: push ebp 0x000000010ac742c8: dec eax 0x000000010ac742c9: sub esp, 0x0000000000000020 ;*synchronization entry ; - java.lang.String::[email protected] (line 1446) ...

Now I guess this is were the real fun starts, happy debugging!