上一篇文章中提到了汇编指令unsafe中getAndAddInt性能疑问 ,正是由于对汇编不甚了解,导致走了很多误区。
这篇文章主要说下如何使用hsdis?
首先给出hsdis的下载地址官方地址,但是官方没有提供Windows的,iteye地址
这篇文章hsdis的使用方式,在OSX、Ubuntu14.04、Centos5.6测试通过,JDK7、JDK8都可。
假设本地hsdis存放目录$HOME/hsdis
下载的hsdis文件,需要根据系统修改为对应的名称,不知道如何修改的,可以根据错误提示修改。
设置环境变量
export LDLIBRARYPATH=$HOME/hsdis
public class Bar {
int a = 1;
static int b = 2;
public int sum(int c) {
return a + b + c;
}
public static void main(String[] args) {
new Bar().sum(3);
}
}
javac Bar.java
java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -Xcomp -XX:CompileCommand=dontinline,Bar.sum -XX:CompileCommand=compileonly,Bar.sum Bar
参数UnlockDiagnosticVMOptions从JDK7的某个版本开始必须加上。
参数PrintAssembly是输出反汇编内容
参数-Xcomp是让虚拟机以编译模式执行代码
参数dontinline是不对Bar.sum方法做内联优化
参数compileonly是仅仅编译Bar.sum方法
下面是汇编代码,这里顺便贴一下
Java HotSpot(TM) 64-Bit Server VM warning: PrintAssembly is enabled; turning on DebugNonSafepoints to gain additional output
CompilerOracle: dontinline Bar.sum
CompilerOracle: compileonly Bar.sum
Loaded disassembler from hsdis-amd64.dylib
Decoding compiled method 0x000000010649b0d0:
Code:
[Disassembling for mach='i386:x86-64']
[Entry Point]
[Constants]
# {method} 'sum' '(I)I' in 'Bar'
# this: rsi:rsi = 'Bar'
# parm0: rdx = int
# [sp+0x20] (sp of caller)
0x000000010649b200: mov 0x8(%rsi),%r10d
0x000000010649b204: shl $0x3,%r10
0x000000010649b208: cmp %r10,%rax
0x000000010649b20b: jne 0x0000000106470960 ; {runtime_call}
0x000000010649b211: data32 xchg %ax,%ax
0x000000010649b214: nopl 0x0(%rax,%rax,1)
0x000000010649b21c: data32 data32 xchg %ax,%ax
[Verified Entry Point]
0x000000010649b220: sub $0x18,%rsp
0x000000010649b227: mov %rbp,0x10(%rsp) ;*synchronization entry
; - Bar::sum@-1 (line 5)
0x000000010649b22c: movabs $0x7aaadbf68,%r10 ; {oop(a 'java/lang/Class' = 'Bar')}
0x000000010649b236: mov 0x70(%r10),%r10d
0x000000010649b23a: add 0xc(%rsi),%r10d
0x000000010649b23e: mov %edx,%eax
0x000000010649b240: add %r10d,%eax ;*iadd
; - Bar::sum@9 (line 5)
0x000000010649b243: add $0x10,%rsp
0x000000010649b247: pop %rbp
0x000000010649b248: test %eax,-0x8ac24e(%rip) # 0x0000000105bef000
; {poll_return}
0x000000010649b24e: retq
0x000000010649b24f: hlt
0x000000010649b250: hlt
0x000000010649b251: hlt
0x000000010649b252: hlt
0x000000010649b253: hlt
0x000000010649b254: hlt
0x000000010649b255: hlt
0x000000010649b256: hlt
0x000000010649b257: hlt
0x000000010649b258: hlt
0x000000010649b259: hlt
0x000000010649b25a: hlt
0x000000010649b25b: hlt
0x000000010649b25c: hlt
0x000000010649b25d: hlt
0x000000010649b25e: hlt
0x000000010649b25f: hlt
[Exception Handler]
[Stub Code]
0x000000010649b260: jmpq 0x00000001064980a0 ; {no_reloc}
[Deopt Handler Code]
0x000000010649b265: callq 0x000000010649b26a
0x000000010649b26a: subq $0x5,(%rsp)
0x000000010649b26f: jmpq 0x0000000106471b00 ; {runtime_call}
0x000000010649b274: hlt
0x000000010649b275: hlt
0x000000010649b276: hlt
0x000000010649b277: hlt
想了解具体的指令是啥含义,可以参考这篇文章JVM执行篇:使用HSDIS插件分析JVM代码执行细节