利用hsdis和JITWatch查看分析HotSpot JIT compiler生成的汇编代码

简介: 安装hsdis要查看JIT生成的汇编代码,要先装一个反汇编器:hsdis。从名字来看,即HotSpot disassembler。


安装hsdis

要查看JIT生成的汇编代码,要先装一个反汇编器:hsdis。从名字来看,即HotSpot disassembler。

实际就是一个动态链接库。网络上有已经编绎好的文件,直接下载即可。

国内的:http://hllvm.group.iteye.com/

也可以自己编绎,只是编绎hsdis,还是比较快的。

参考这里:http://www.chrisnewland.com/building-hsdis-on-linux-amd64-on-debian-369


官方的参考文档:

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

简而言之,安装只要把下载到,或者编绎好的so文件放到对应的Java安装路径下即可。

典型的情况是把下载到的 hsdis-amd64.so 放到 /usr/lib/jvm/java-7-oracle/jre/lib/amd64/ 目录下。

可以用下面这个命令来查看是否安装成功。

java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -version

如果输出有:

Java HotSpot(TM) 64-Bit Server VM warning: PrintAssembly is enabled

则安装成功。

安装JITWatch

hsdis自然是很重要,但是今天的主角是JITWatch,一个分析展现JIT日志等的图形界面工具,非常的好用。

https://github.com/AdoptOpenJDK/jitwatch

首先下载jar包,这里下载的是JDK7版本的:

wget https://adopt-openjdk.ci.cloudbees.com/job/jitwatch/jdk=JDK_1.7/ws/jitwatch-1.0.0-SNAPSHOT-JDK_1.7.tar.gz

解压得到jar 文件。

下载代码文件,主要是为了相关的依赖jar:

wget  https://github.com/AdoptOpenJDK/jitwatch/archive/master.zip

解压,从lib目录得到相关的jar包。和前面得到的JITWatch的jar包放在一起。

用这个命令启动:

java -cp /usr/lib/jvm/java-7-oracle/lib/tools.jar:/usr/lib/jvm/java-7-oracle/jre/lib/jfxrt.jar:jitwatch-1.0.0-SNAPSHOT.jar:slf4j-api-1.7.7.jar:hamcrest-core-1.3.jar:logback-classic-1.1.2.jar:logback-core-1.1.2.jar com.chrisnewland.jitwatch.launch.LaunchUI

启动后显示的界面如下,左上方有一个sanbox的按钮,点击会在当前目录下生成一个sanbox文件夹,里面存放着sanbox这个示例相关的代码。


点击sanbox就可以随便尝试下功能了。

生成JIT log文件

首先要写一个足够复杂的类,让JIT编绎器认为它需要进行优化,不然产生的日志可能没什么内容。我在这里被坑了不少时间,怎么死活都没有日志。。

public class Test {
	public volatile long sum = 0;
	
	public int add(int a, int b) {
		int temp = a + b;
		sum += temp;
		return temp;
	}

	public static void main(String[] args) {
		Test test = new Test();

		int sum = 0;

		for (int i = 0; i < 1000000; i++) {
			sum = test.add(sum, 1);
		}

		System.out.println("Sum:" + sum);
		System.out.println("Test.sum:" + test.sum);
	}
}

加上一些参数来执行程序,就可以直接生成JIT log文件了,比如为Test类生成:

javac Test.java
java -server -XX:+UnlockDiagnosticVMOptions -XX:+TraceClassLoading  -XX:+PrintAssembly -XX:+LogCompilation -XX:LogFile=live.log  Test

注意生成的log文件里,可能会有一些class path相关的东东,所以JITWatch有可能会解析失败。这时注意看左下的“Errors”。

个人推荐在Eclipse里配置生成JIT log,这样使用起来更方便。

在“Run Configuration”里配置上JVM参数:

-server -XX:+UnlockDiagnosticVMOptions -XX:+TraceClassLoading  -XX:+PrintAssembly -XX:+LogCompilation -XX:LogFile=${java_type_name}.log

然后,当执行时,会自动生成JIT log。

在JITWatch里,“Open Log",打开生成的Test.log,然后配置config:


然后,点”Start"就可以查看到分析的结果了。

这是一个分析结果的展示,左边是源代码,中间是ByteCode,右边是汇编代码:


JITWatch还有很多强大的功能。具体请参考wiki:

https://github.com/AdoptOpenJDK/jitwatch/wiki

比如查看函数是否inline,循环展开,分支预测等。

作者有一个PDF介绍:

http://www.chrisnewland.com/images/jitwatch/HotSpot_Profiling_Using_JITWatch.pdf

视频:

https://skillsmatter.com/skillscasts/5243-chris-newland-hotspot-profiling-with-jit-watch

Java里volatile的实现

从生成的汇编代码,可以看出Java里volatile的实现是用lock指令前缀来实现的:

0x00007f80950601b0: lock addl $0x0,(%rsp)  ;*putfield sum
                                           ; - Test::add@12 (line 6)
                                           ; - Test::main@18 (line 16)

更加关于lock指令前缀,请参考这里:

http://stackoverflow.com/questions/8891067/what-does-the-lock-instruction-mean-in-x86-assembly


参考:

http://psy-lob-saw.blogspot.com/2013/01/java-print-assembly.html

http://www.chrisnewland.com/images/jitwatch/HotSpot_Profiling_Using_JITWatch.pdf

相关文章
|
3月前
|
网络协议 C++
解决MASM32代码汇编出错: error A2181: initializer must be a string or single item
解决MASM32代码汇编出错: error A2181: initializer must be a string or single item
|
4月前
|
存储 算法 程序员
神秘代码世界惊现高效秘籍!究竟是什么让汇编语言编程如此强大?快来一探究竟!
【8月更文挑战第31天】《代码之美:探索高效汇编语言编程的最佳实践》介绍了汇编语言在系统内核、嵌入式系统及高性能应用中的不可替代作用。书中强调了深入理解处理器架构、提升代码可读性、优化算法与数据结构及有效利用寄存器等最佳实践的重要性。通过具体示例,如在 x86 架构下实现高效的加法函数,展示了如何运用这些技巧编写出既高效又可靠的汇编代码,充分展现了汇编语言的独特魅力及其在现代软件开发中的价值。
46 0
|
3月前
|
Windows
【原创】DOS下TSR程序的汇编演示代码2--黑屏保护程序
【原创】DOS下TSR程序的汇编演示代码2--黑屏保护程序
【原创】DOS下TSR程序的汇编演示代码1--自动按键程序
【原创】DOS下TSR程序的汇编演示代码1--自动按键程序
|
4月前
|
NoSQL 前端开发 程序员
【震撼揭秘!】程序员绝不会告诉你的秘密:掌握汇编语言调试,轻松从软件故障中全身而退——透视代码底层,成为Bug猎人!
【8月更文挑战第31天】《调试的艺术:如何利用汇编语言追踪和解决软件问题》探讨了使用汇编语言进行高效调试的方法。无论是初学者还是资深开发者,面对棘手的 bug 时,高级语言的信息往往不足。文章通过具体示例展示如何通过汇编代码定位问题,如 C 语言中数组求和函数的崩溃问题。借助 `gcc -S` 生成的汇编代码和 GDB 调试器,可以深入理解程序行为,从而更准确地解决问题。掌握这一技能,将使你在复杂问题面前更加从容。
44 2
|
4月前
|
C语言
51单片机汇编语言流水灯代码
51单片机汇编语言流水灯代码
|
4月前
|
C# 开发者 图形学
Xamarin 竟在游戏开发领域大胆探索,跨平台优势与强大功能结合,开启游戏开发新潮流!
【8月更文挑战第31天】《Xamarin在游戏开发领域的探索》介绍了Xamarin作为跨平台开发框架,在移动游戏开发中的应用。它利用C#语言的优势,提供高效的开发体验,并结合各平台图形库实现高质量画面。本文还展示了Xamarin如何简化游戏逻辑处理、支持多线程编程及与Unity等工具集成,提升游戏质量和开发效率。此外,Xamarin还支持热更新和多平台发布,进一步优化游戏维护流程。
44 0
|
7月前
|
Java C++
如何在JAVA代码中嵌入汇编
如何在JAVA代码中嵌入汇编
111 1
|
6月前
|
Python
python 代码脚本汇编
python 代码脚本汇编
49 0
|
7月前
|
Windows
86/88汇编代码的运行调试
86/88汇编代码的运行调试
43 0