背景
Java代码通过编译器编译成字节码(class文件),由jVM的各个类加载器加载后,根据JVM的启动配置可以进行解释执行和编译执行。
编译执行是由JIT(Just In Time) Compiler将字节码一次性编译成本地代码来提高执行速度。缺点是编译本身会消耗并且会占用堆外空间(codecache中),但是一般Server应用内存足够且能够忍受启动时的略微缓慢。
查看源代码对应的字节码:javap
查看汇编代码请继续向下看。
分析程序如何执行时,大量自行代码时通过JIT编译器动态生成到CodeBuffer中的,通过软件条件工具(GDB、Windbg等)断点调试的方式在Java虚拟机中会遇到很大困难,HSDIS插件是Sun官方推荐的HotSpot虚拟机JIT编译代码的反汇编插件,下面介绍如何在Mac平台下使用。
安装HSDIS
查看是否安装HSDIS:
java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -version | grep Java HotSpot(TM)
如果有,则输出
没有,则下载
前者是Mac 64位机器,后者是Linux 64位机器。
下载后将hsdis-amd64.so
放到jdk1.version.jdk/Contents/Home/jre/lib/amd64
。
安装JITWatch
分析展现JIT日志等的图形界面工具
1 | git clone https://github.com/AdoptOpenJDK/jitwatch |
1 | mvn clean install -DskipTests=true |
1 | ./launchUI.sh |
代码
1 | import java.util.concurrent.CountDownLatch; |
添加JVM参数
用于生成hotspot.log
文件
.java
文件
1 | -XX:+UnlockDiagnosticVMOptions -XX:+TraceClassLoading -XX:+PrintAssembly -XX:+LogCompilation -XX:LogFile=jit.log |
添加参数后直接运行,会产生jit.log
文件
Maven项目
有的项目会用maven,就用下面的方式添加参数,此处不用操作,仅仅作为说明
1 | export "MAVEN_OPTS=$MAVEN_OPTS -XX:+UnlockDiagnosticVMOptions -XX:+TraceClassLoading -XX:+LogCompilation -XX:+PrintAssembly" |
- 父目录执行
1 | mvn tomcat:run |
我们要开始玩啦~
- 打开
JITWatch
界面,点击Open Log
,选择jit.log
,点击Start
。 - 点击左侧
Packages
下的类,双击右侧具体的方法,可以打开TriView
界面,在最右侧可以看到Assembly
代码
重点来了
我的没有!!!
Assembly not found. Was -XX:+PrintAssembly option used?
经查阅,是因为
JITWatch
以前和FCML反汇编程序
一起运行的bug,目前已经解决,但是看完了我也没懂到底我要干嘛,继续查文档…看到了刘正阳—hsdis,按照文档说明操作了一把,泪奔……终于看到了
正确姿势
- 编译hsdis
make ARCH=AMD64
- 将dylib复制到JDK目录中
如果JDK版本不同需要修改路径中版本号
1 | sudo cp build/macosx-amd64/hsdis-amd64.dylib /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/server/ |
- 再打开JITWatcher就可以看到了