当前环境:jdk1.8,win10,64位

打印Java汇编指令

使用hsdis工具打印汇编指令,可以自行编译或者下载已编译好的dll或so文件,并将文件拷贝至jdk安装目录下的bin/server或者bin/client,例如:D:\Program Files\Java\jdk1.8.0_131\bin\server\hsdis-amd64.dll
或执行:export LD_LIBRARY_PATH=/hsdis路径
windows下编译教程:https://dropzone.nfshost.com/hsdis/ mac: https://kenai.com/projects/base-hsdis/downloads/directory/gnu-versions,或:
执行Java命令增加如下参数,参考:https://wiki.openjdk.java.net/display/HotSpot/PrintAssembly 或者可以将参数放在标志文件中并通过参数指定标志配置文件:-XX:Flags=myhotspotrc.txt

-server 
-XX:+UnlockDiagnosticVMOptions // 由于下面的参数属于诊断参数,所以在使用之前需要打开UnlockDiagnosticVMOptions参数
-XX:+TraceClassLoading 
-XX:+PrintAssembly // 为字节码与本地方法打印汇编代码print assembly code for bytecoded and native methods
-XX:+LogCompilation 
-XX:+DebugNonSafepoints (日志非常多,可以选择不加该参数)
-XX:LogFile=VisibilityWithoutVolatile.log // 指定日志文件
-Xcomp // JVM在第一次执行时便会把所有的字节码编译成本地代码
-XX:CompileCommand=compileonly,*VisibilityWithoutVolatile.* 仅编译指定类的某个方法,星号代表所有方法(会丢失很多内容,不要为了减少日志而增加该参数,因小失大-_-!!!)
// 不需要加该参数:-XX:CompileCommand=dontinline,*VisibilityWithoutVolatile.* 内联问题,可以指定不对某些方法进行jit编译,跳过有问题方法的编译 // Allow use of -XX:CompileCommand=dontinline to exclude problematic methods

使用jitwatch分析日志

使用方法参考:https://github.com/AdoptOpenJDK/jitwatch 博主是通过mvn引入pom依赖,然后直接执行jitwatch的main方法开始使用。源码地址:https://github.com/GallantKong/jitwatch-example

import org.adoptopenjdk.jitwatch.launch.LaunchUI;

/**
 * @author 会灰翔的灰机
 * @date 2019/10/30
 */
public class JITWatchMain {

    public static void main(String[] args) {
        LaunchUI.main(args);
    }
}

--pom.xml

<dependency>
  <groupId>com.chrisnewland</groupId>
  <artifactId>jitwatch-parent</artifactId>
  <version>1.1.5</version>
  <type>pom</type>
</dependency>
<dependency>
  <groupId>com.chrisnewland</groupId>
  <artifactId>jitwatch</artifactId>
  <version>1.1.5</version>
</dependency>
<dependency>
  <groupId>com.chrisnewland</groupId>
  <artifactId>jitwatch-ui</artifactId>
  <version>1.1.5</version>
</dependency>

配置jitwatch

源码文件目录

字节码文件目录

java到汇编再到二进制 java调用汇编_jitwatch

问题

不显示源码

不显示源码问题主要因为源码路径配置不对,需要配置到源码的具体所在目录,jitwatch不会自动递归目录查找源码

不显示汇编代码

全部显示没有汇编代码,或者部分显示有汇编代码,部分没有。案例如图:显示不是JIT编译代码

java到汇编再到二进制 java调用汇编_java到汇编再到二进制_02

  1. jvm在方法执行达到一定的热度才会将代码编译成特定平台的汇编语言执行,使用-Xcomp参数指定jvm在第一次执行时把所有的字节码编译成本地代码
  2. 大型方法会在执行到限制时才会执行编译。所以平时不建议大家方法写的过大跟该参数的默认启用有些关系
-XX:+DontCompileHugeMethods // 打开不编译巨大的方法,直至达到限制
-XX:HugeMethodLimit=8000 // HotSpot VM默认不会JIT编译字节码大小超过8000字节的方法

方法汇编代码显示级别不同

  1. 如下图:run方法显示级别为#3(C2/OSR/level4);main方法提示级别为#2(C2/level4)