Java启用-XX:+PrintAssembly仅输出十六进制指令无业务汇编问题
问题原因
- 汇编仅显示十六进制值,核心原因是缺少
hsdis反汇编插件。安装openjdk-17-dbg仅能提供JVM本身的调试符号,不包含JIT生成代码的反汇编组件,JVM无法将输出的机器码翻译为可读汇编助记符,只能打印原始字节。 - 输出全是JDK内置方法、看不到自定义代码,由两个问题共同导致:
- JIT编译为触发式机制,默认分层编译模式下,方法需要被调用1500次以上才会触发C1编译,调用1万次以上才会触发C2最高等级优化编译。测试代码中自定义构造方法、
fun()、main()仅执行1次,达不到JIT编译阈值,始终以解释模式运行,而PrintAssembly只会输出JIT编译生成的本地代码,不会处理解释执行的字节码。 - 未配置编译过滤规则,JVM启动阶段会提前加载、编译大量JDK核心类方法,海量内置方法的汇编输出直接淹没了自定义方法的内容。
- JIT编译为触发式机制,默认分层编译模式下,方法需要被调用1500次以上才会触发C1编译,调用1万次以上才会触发C2最高等级优化编译。测试代码中自定义构造方法、
配置步骤
- 第一步:安装hsdis反汇编插件,执行命令
sudo apt install openjdk-17-hsdis,安装完成后JVM即可正常解析输出汇编助记符。 - 第二步:调整JVM启动参数,强制编译自定义方法、过滤无关输出,完整参考命令如下:
java -XX:+UnlockDiagnosticVMOptions \ -XX:+PrintAssembly \ -Xcomp \ -XX:-TieredCompilation \ -XX:CompileCommand=compileonly,*Main.main,*Dervied.<init>,*Dervied.fun \ Main
参数说明:
-Xcomp:告知JVM首次执行方法时就直接进行编译,不需要等待调用次数达到阈值,适合短生命周期的测试程序。-XX:-TieredCompilation:关闭分层编译,直接使用C2编译器生成最高优化等级的本地代码,和提到的-XX:+PrintOptoAssembly输出的优化后代码逻辑一致(PrintOptoAssembly需要debug版JVM输出编译中间阶段的汇编,PrintAssembly输出最终加载到代码缓存的可执行机器码,普通release版JVM装完hsdis即可使用)。-XX:CompileCommand=compileonly,...:指定仅编译列出的自定义方法,直接屏蔽所有JDK内置方法的编译和汇编输出,不会再出现满屏无关内容的问题。- 如果需要查看C1编译阶段的汇编输出,去掉
-XX:-TieredCompilation参数即可。
内容的提问来源于stack exchange,提问作者Susano
相关产品推荐
相关产品推荐

