小师妹学JVM之JIT中的PrintAssembly

5次阅读

共计 2106 个字符,预计需要花费 6 分钟才能阅读完成。

简介

想不想了解 JVM 最最底层的运行机制?想不想从本质上理解 java 代码的执行过程?想不想对你的代码进行进一步的优化和性能提升?

如果你的回答是 yes。那么这篇文章非常适合你,因为本文将会站在离机器码最近的地方来观看 JVM 的运行原理:Assembly。

使用 PrintAssembly

小师妹:F 师兄,上次你给我介绍了 java 中的字节码,还有 JIT 中的 LogCompilation 和 PrintCompilation 的用法。虽然都非常有用,但是能不能更进一步,让我能以机器的眼光来看待 JVM 的执行?

小师妹,如果要探究 JVM 的运行本质,那就应该是机器码了。难道你要去读懂机器码?虽然我不是机器码的专家,但我猜那应该是个非常复杂的过程。

小师妹:F 师兄,当然不是机器码,有没有比机器码更高级一点点的,我记得上大学的时候学过汇编语言,好像就是离机器码最近的语言了,JVM 有没有相应的汇编语言呢?

必须有的,我们可以使用 -XX:+PrintAssembly 来将 assembly 打印出来。

但是打印 assembly 是有条件的,它就像一个高傲的姑娘,不是你想追求就能追求得上的。

我们使用下面的命令来查看系统对 PrintAssembly 的支持程度:

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

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
java version "1.8.0_171"
Java(TM) SE Runtime Environment (build 1.8.0_171-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.171-b11, mixed mode)

根据大家的运行环境的不同,得到的结果可能也是不同的,我是 mac 的系统,从上面的结果可以看到,在我的 JDK8 的环境中,显示缺少 hsdis-amd64.dylib,所以 PrintAssembly 其实是禁用的。

小师妹:F 师兄,那现在咋办呀?没有 hsdis-amd64.dylib 就用不了 PrintAssembly 了。

巴甫洛夫说过:问号是开启任何一门科学的钥匙。没有问题我们就创造问题,没有困难我们就制造困难,没有 hsdis-amd64.dylib 当然是安装咯。

具体怎么安装,大家自行探索吧,网上有很多安装的教程,这里就不一一介绍了。

这里想讨论一个很奇怪的事情,虽然在 JDK8 环境中,我们不能使用 PrintAssembly,因为没有 hsdis-amd64.dylib。但是当我切到最新的 JDK14 环境中,一切都很美好,PrintAssembly 可以正常运行了。

如果我们在 JDK14 中同样运行上面的命令,我们会得到下面的结果:

上图说明 JDK14 中虽然可以正常运行但是结果却不是 assembly code,说明在 JDK14 中还是需要安装 hsdis-amd64.dylib 才能够得到正确的 assembly 结果。

注意,JDK14 也需要安装 hsdis-amd64.dylib 才能正确使用。

输出过滤

默认情况下,PrintAssembly 输出的是所有的信息,但是 JDK 内部的代码我们不可能进行修改,一般来说并不关心他们的 assembly 输出,如果要指定我们自己编写的方法,可以使用 CompileCommand:

CompileCommand=print,*MyClass.myMethod prints assembly for just one method
CompileCommand=option,*MyClass.myMethod,PrintOptoAssembly (debug build only) produces the old print command output
CompileCommand=option,*MyClass.myMethod,PrintNMethods produces method dumps

例如:

-XX:CompileCommand=print,com.flydean.PrintAssemblyUsage::testPrintAssembly

这样我们可以得到,只属于 testPrintAssembly 方法的输出:

总结

本文讲解了怎么使用 PrintAssembly 来输出 JVM 的汇编日志。我们会在后面继续讲解这些 Assembly code 到底有什么用。

本文的例子 https://github.com/ddean2009/learn-java-base-9-to-20

本文作者:flydean 程序那些事

本文链接:http://www.flydean.com/jvm-jit-printassembly/

本文来源:flydean 的博客

欢迎关注我的公众号: 程序那些事,更多精彩等着您!

正文完
 0