简介

上篇文章和小师妹一起介绍了PrintAssembly和PrintAssembly在命令行的使用,今天本文将会更进一步讲解如何在JDK8和JDK14中分别使用PrintAssembly,并在实际的例子中对其进行进一步的深入理解。

JDK8和JDK14中的PrintAssembly

小师妹:F师兄,上次你介绍的PrintAssembly的自测命令,怎么在JDK14中不好用呢?

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

有什么不好用的,命令不是正常打出来了吗?

小师妹:F师兄,你看下我运行的结果,机器码下面展示的怎么是448b 5608这样的数字呀,不应该是assembly language吗?

嗯...小师妹的话让我陷入了深深的思考,究竟是什么导致了这样的反常的结果呢?是道德的沦丧还是人性的扭曲?

于是我翻遍了baidu,哦,不对是google,还是没有找到结果。

难点是JDK14有bug?还是JDK14已经使用了另外的Assembly的实现?

有问题就解决问题,我们先从JDK8开始,来探索一下最原始的PrintAssembly的使用。

更多精彩内容且看:

JDK8中使用Assembly

在JDK8中如果我们运行Assembly的测试命令,可以得到下面的结果:

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)

这个故事告诉我们,虽然PrintAssembly开关打开了,但是系统不支持,缺少了hsdis-amd64.dylib文件。

这个hsdis是一个反汇编的工具,我们需要hsdis的支持才能在JDK8中使用Assembly。

我是mac系统,下面是在mac系统怎么安装hsdis:

hg clone http://hg.openjdk.java.net/jdk8u/jdk8u

cd jdk8u/hotspot/src/share/tools/hsdis/

wget http://ftp.heanet.ie/mirrors/ftp.gnu.org/gnu/binutils/binutils-2.30.tar.gz

tar -xzf binutils-2.30.tar.gz

make BINUTILS=binutils-2.30 ARCH=amd64

#java8
sudo cp build/macosx-amd64/hsdis-amd64.dylib /Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/server/ #java9 onwards
sudo cp build/macosx-amd64/hsdis-amd64.dylib /Library/Java/JavaVirtualMachines/jdk-9.0.4.jdk/Contents/Home/lib/server/

如果你是linux或者windows系统,请自行探索hsdis的安装方法。

按照步骤先把java8的hsdis-amd64.dylib安装好。

然后再次运行测试命令:

完美,汇编语言出现了。

JDK14中的Assembly

然后我想到,如果把这个dylib文件拷贝到JDK14相应的目录下面,运行一次会怎么样呢?

大家注意,JDK9之后,使用了模块化,所以之前的目录结构发生了比较大的变化,大家参考上面我列出的地址。

再次运行测试代码:

大家看到,Assembly又出现了,真的是让我热内盈亏。

其实最开始的时候,我发现JDK14中Assembly没能正常显示的时候,我也有想过拷贝一个hsdis-amd64.dylib过来试试,但是一看还需要下载JDK的代码,重新编译,就打起了退堂鼓。

吃一堑,长一智,下次遇到问题千万不能走捷径。抄近路害死人呀!

在JMH中使用Assembly

Assembly主要是为了进行代码调优或者理解JVM的运行原理来使用的。

这里我们举一个在JMH中使用Assembly的例子:

@Warmup(iterations = 2, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 2, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(value = 1,
jvmArgsPrepend = {
"-XX:+UnlockDiagnosticVMOptions",
"-XX:CompileCommand=print,com.flydean.PrintAssemblyUsage::testPrintAssembly"
}
)
@State(Scope.Benchmark)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class PrintAssemblyUsage { int x;
@Benchmark
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
public void testPrintAssembly() {
for (int c = 0; c < 1000; c++) {
synchronized (this) {
x += 0xFF;
}
}
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(PrintAssemblyUsage.class.getSimpleName())
.build(); new Runner(opt).run();
}
}

上面的例子中,我们使用了-XX:CompileCommand指定要打印的方法,而不是输出所有的Assembly,方便我们查看和分析结果。

总结

本文介绍了JDK8和JDK14中,怎么开启PrintAssembly。并举了一个在JMH中使用的例子。

那么有人会问了,在JMH中使用Assembly到底有什么意义呢?别急,我们在后面深入JVM的本质中,马上就要讲到,敬请期待。

本文作者:flydean程序那些事

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

本文来源:flydean的博客

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

小师妹学JVM之:JIT中的PrintAssembly续集的更多相关文章

  1. 小师妹学JVM之:JIT中的PrintAssembly

    目录 简介 使用PrintAssembly 输出过滤 总结 简介 想不想了解JVM最最底层的运行机制?想不想从本质上理解java代码的执行过程?想不想对你的代码进行进一步的优化和性能提升? 如果你的回 ...

  2. 小师妹学JVM之:JIT中的LogCompilation

    目录 简介 LogCompilation简介 LogCompilation的使用 解析LogCompilation文件 总结 简介 我们知道在JVM中为了加快编译速度,引入了JIT即时编译的功能.那么 ...

  3. 小师妹学JVM之:JIT中的PrintCompilation

    目录 简介 PrintCompilation 分析PrintCompilation的结果 总结 简介 上篇文章我们讲到了JIT中的LogCompilation,将编译的日志都收集起来,存到日志文件里面 ...

  4. 小师妹学JVM之:JDK14中JVM的性能优化

    目录 简介 String压缩 分层编译(Tiered Compilation) Code Cache分层 新的JIT编译器Graal 前置编译 压缩对象指针 Zero-Based 压缩指针 Escap ...

  5. 小师妹学JVM之:深入理解JIT和编译优化-你看不懂系列

    目录 简介 JIT编译器 Tiered Compilation分层编译 OSR(On-Stack Replacement) Deoptimization 常见的编译优化举例 Inlining内联 Br ...

  6. 小师妹学JVM之:JVM中的Safepoints

    目录 简介 GC的垃圾回收器 分代回收器中的问题 safepoints safepoint一般用在什么地方 总结 简介 java程序员都听说过GC,大家也都知道GC的目的是扫描堆空间,然后将那些标记为 ...

  7. 小师妹学JVM之:cache line对代码性能的影响

    目录 简介 一个奇怪的现象 两个问题的答案 CPU cache line inc 和 add 总结 简介 读万卷书不如行万里路,讲了这么多assembly和JVM的原理与优化,今天我们来点不一样的实战 ...

  8. 小师妹学JVM之:JVM的架构和执行过程

    目录 简介 JVM是一种标准 java程序的执行顺序 JVM的架构 类加载系统 运行时数据区域 执行引擎 总结 简介 JVM也叫Java Virtual Machine,它是java程序运行的基础,负 ...

  9. 小师妹学JavaIO之:NIO中那些奇怪的Buffer

    目录 简介 Buffer的分类 Big Endian 和 Little Endian aligned内存对齐 总结 简介 妖魔鬼怪快快显形,今天F师兄帮助小师妹来斩妖除魔啦,什么BufferB,Buf ...

随机推荐

  1. Java实现第八届蓝桥杯9算数式

    9算数式 题目描述 观察如下的算式: 9213 x 85674 = 789314562 左边的乘数和被乘数正好用到了1~9的所有数字,每个1次. 而乘积恰好也是用到了1~9的所有数字,并且每个1次. ...

  2. centos 7 源码安装openssh

    环境:centos 7.1.1503 最小化安装 依赖包下载:  yum -y install lrzsz zlib-devel perl gcc pam-devel 1.安装openssl ,选用最 ...

  3. (一)SQL注入漏洞测试的方式总结

    一.工具注入 1.SQLMap的作用 判断可注入的参数 判断可以用那种SQL注入技术来注入 识别出哪种数据库 根据用户选择,读取哪些数据(库.表.列.字段值...) 2.注入技术 [A]基于布尔的盲注 ...

  4. “造轮运动”之 ORM框架系列(三)~ 干货呈上

     这一趴里面,我就来正式介绍一下CoffeeSQL的干货.    首先要给CoffeeSQL来个定位:最开始就是由于本人想要了解ORM框架内部的原理,所以就四处搜寻有关的博客与学习资料,就是在那个夏天 ...

  5. 二叉树路径搜索---DFS 路径和

    vector<vector<int>> pathSum(TreeNode* root,int sum){//DFS遍历获取适合路径,当递归到叶子结点且sum为0,表示该路径合适 ...

  6. Cookie默认不设置path时,哪些请求会携带cookie数据

    默认不设置path的时候,只会在请求和servlet同路径的情况下才会携带cookie中存储的数据,包含同级目录和下级目录 例如: 在http://localhost:8080/day01/test/ ...

  7. Java与Swift对比

    本文链接:http://blog.csdn.net/msyqmsyq/article/details/53538159 从Java到Swift还是比较简单的,相比Object-C,Swift和Java ...

  8. 分享一个springboot脚手架

    项目介绍 在我们开发项目的时候各个项目之间总有一些可共用的代码或者配置,如果我们每新建一个项目就把代码复制粘贴再修改就显得很没有必要.于是我就做了一个 poseidon-boot-starter 该项 ...

  9. Chrome扩展移植到Edge浏览器教程

    微软在推出Edge浏览器之初,就把能够使用扩展(extension)作为一个重要功能.在Win10一周年更新版(1607)中,这项功能正式向广大用户推出(当然,Insider用户早就测试了一段时间了) ...

  10. <Win10开发>UWP使用.Net Native编译时遇到的一些问题。

    最近开始尝试把WP8.1 Runtime的项目升级成Win10 UWP,我用的方法没什么技巧性,就是直接复制文件和代码到新建的UWP项目.结果是后台代码未经修改,全部正常运行.但是UI控件的布局有些偏 ...