Java 字节码反编译成汇编插件
环境:
(1)windows10环境
(2)jdk “1.8.0_261” 64位
(3)Java HotSpot™ 64-Bit Server VM (build 25.261-b12, mixed mode)
一、报错详情
报错提示(如下图):Java HotSpot(TM) 64-Bit Server VM warning: PrintAssembly is enabled; turning on DebugNonSafepoints to gain additional output
也可使用cmd测试重现:java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -version
二、解决方法
1、下载并配置环境
(1)确保已安装jdk1.8
(2)安装hsdis-amd64.dylib 和 hsdis-amd64.dll
①下载hsdis-amd64.dylib,网盘下载地址(验证码:hhg5)
将下载好的hsdis-amd64.dylib文件放置在JDK路径下的\jre\lib目录下。
②下载hsdis-amd64.dll,网盘下载地址(验证码:mdpg)
将下载好的hsdis-amd64.dll文件放置在JDK路径下\jre\bin\server目录下。
(2)在cmd中使用命令java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -version
验证是否配置成功。如果出现如下所示则说明配置成功。
2、IDEA软件中测试
测试类:
package com.company.thread;
/**
* @author: zhangxh
* @date: 2023/03/29 08:39
* @Desc: 可见性问题测试
*
* 运行方法:
* (1)cd 到当前类目录
* (2)cdm执行命令:java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -Xcomp
*/
public class VisibilityTest {
private boolean flag = true;
public void refresh() {
flag = false;
System.out.println(Thread.currentThread().getName() + "修改flag");
}
public void load() {
System.out.println(Thread.currentThread().getName() + "开始执行.....");
int i = 0;
while (flag) {
i++;
//TODO 业务逻辑
}
System.out.println(Thread.currentThread().getName() + "跳出循环: i=" + i);
}
public static void main(String[] args) throws InterruptedException {
VisibilityTest test = new VisibilityTest();
// 线程threadA模拟数据加载场景
Thread threadA = new Thread(() -> test.load(), "threadA");
threadA.start();
// 让threadA执行一会儿
Thread.sleep(1000);
// 线程threadB通过flag控制threadA的执行时间
Thread threadB = new Thread(() -> test.refresh(), "threadB");
threadB.start();
System.out.println("sss");
}
public static void shortWait(long interval) {
long start = System.nanoTime();
long end;
do {
end = System.nanoTime();
} while (start + interval >= end);
}
}
使用命令java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -XX:CompileCommand=print,*VisibilityTest.main
注: 使用CompileCommand命令反编译指定代码方法。
CompileCommand 参数:
作用:用来定制编译需求,可以指定某个方法不做 JIT 编译,也可以只编译指定的方法等等。
语法:
-XX:CompileCommand=command,method[,option]
其中的 command 有下面这些选项:
- exclude,跳过编译指定的方法
- compileonly,只编译指定的方法
- inline/dontinline,设置是否内联指定方法
- print,打印生成的汇编代码
- break,JVM以debug模式运行时,在方法编译开始处设置断点
- quiet,不打印在此命令之后、通过-XX:CompileCommand指定的编译选项
- log,记录指定方法的编译日志,若未指定,则记录所有方法的编译日志
- 其他命令,option,help
上面的测试命令: -XX:CompileCommand=print,*VisibilityTest.main
,仅反编译VisibilityTest的main方法。