java查看运行代码的汇编指令(含hsdis-arm64.dll文件)
Posted luffy5459
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java查看运行代码的汇编指令(含hsdis-arm64.dll文件)相关的知识,希望对你有一定的参考价值。
本文来自bilibili上的Java系列视频,需要额外的工具就是hsdis-arm64.dll文件。工具下载百度网盘链接:https://pan.baidu.com/s/1Q7kvS3a8YYXfaV3_OjNjBg 提取码:fvzm
普通的Java代码执行,无法看到汇编指令,若要查看,需要下载hsdis动态链接库。一般网上介绍的都是mac下的hsdis.dylib,这里介绍是win10下的dll。
这个工具需要放在jdk安装目录下的jre/bin目录下。
运行代码的时候指定jdk为jre。
准备一个Java代码:
package org.example;
public class VolatileVisibilityTest
private static volatile boolean initFlag = false;
public static void main(String[] args) throws InterruptedException
new Thread(()->
System.out.println("waiting data.....");
while (!initFlag)
System.out.println("=========success.");
).start();
Thread.sleep(2000);
new Thread(()->prepareData()).start();
public static void prepareData()
System.out.println("prepare data end.");
initFlag = true;
这个程序启动两个线程,一个线程依赖全局变量initFlag会做无限循环,直到initFlag发生改变,循环退出。另一个线程启动去尝试修改initFlag。一般认为,程序会依次打印waiting data,prepare data end,success信息,最后退出。实际上,如果不加volatile关键字,这个程序只是打印waiting data,prepare data end,并不会最终终止。
以上代码,如果不加volatile关键字修饰,程序运行结果:
线程运行在不同的CPU上,各自无法感知initFlag变量发生了改变,所以线程会挂住,一直在等待initFlag发生变化。
当代码加上volatile关键字,程序运行结果如下所示:
程序经历2秒之后,最终initFlag发生改变,所有线程均感知到,并退出while循环,打印success。最后主线程退出。
idea下,点击Edit Configurations,弹出框中设置环境以及虚拟机参数:
虚拟机参数完整内容:
-server
-Xcomp
-XX:+UnlockDiagnosticVMOptions
-XX:+PrintAssembly
-XX:CompileCommand=compileonly,*VolatileVisibilityTest.prepareData
运行结果截图:
volatile缓存可见性实现原理:
底层实现主要是通过汇编lock前缀指令,它会锁定这块内存区域的缓存,然后写入主内存。
IA-32和intel64架构软件开发者手册对lock指令的解释:
1)会将当前处理器缓存行的数据立即写回到系统内存
2)写回内存的操作会引起其他CPU缓存了该内存地址的数据无效(缓存一致性协议MSEI)
3) 提供内存屏障功能,使lock前后指令不能重排序
通过上面的汇编指令查看工具,最后运行加了volatile关键字的代码就如前面那样,出现很多汇编指令。并且程序顺利终止。在大量的汇编指令中,我们可以看到如下片段:
这个lock指令就是前面提到的volatile底层实现原理,他通过lock前缀指令锁定该内存,发生改变之后,立即写入主内存,其他缓存了该内存地址的CPU工作内存会失效,而需要读取主内存中的变量,所以程序最终按照预期完成所有操作并退出。
以上是关于java查看运行代码的汇编指令(含hsdis-arm64.dll文件)的主要内容,如果未能解决你的问题,请参考以下文章