令人惊奇的是,居然还有办法查看一个Java方法的汇编代码JIT编译出来的方法的汇编代码。这篇文章我们从零开始,详细说说如何查看java方法的字节码和汇编代码,希望能给在这方面迷茫的同学提供一些帮助。为了真正从零开始,我们自己动手,通过源码构建自己的jdk。虽然这个过程不是必须的,但是理解这些过程,有助于我们理解后面以及后续的jvm研究。绝对有帮助。首先,下载jdk源码:$gitclonehttps://github.com/openjdk/jdk.git源码下载完成后,我们看一下jdk里面大概的目录结构:doc/building.html这个目录里面详细介绍了如何搭建一个jdk,有兴趣的同学可以好好看看。在jdk目录下,我们执行如下命令构建一个debug版本的jdk,并指定其安装路径为jdk-build:$bashconfigure--with-debug-level=slowdebug--with-native-debug-symbols=internal--prefix=$HOME/jdk-build这条命令执行过程中如果没有问题,会有类似下图的输出:configure命令执行成功后,我们再执行下面的命令开始实际构建jdk,andbuild成功的jdk安装在jdk-build目录下:$makeimages$makeinstall上面两条命令成功后,我们可以切换到jdk-build目录下,看看新建的jdk:好了,我们已经有了我们自己的jdk,下面我们可以用它来查看java方法的字节码和汇编代码。首先准备好以下文件:先来看看如何查看字节码。这个大家应该都知道,但是我在这里演示一下:上图是通过jdk自带的javap命令查看java的字节码。其实还有很多其他的方式,比如各种IDE中集成的工具,这里就不一一演示了。javap还有很多参数,比如-p-v都很好用,有兴趣的可以自己试试。这就是字节码的全部内容。下面主要看看如何查看java方法的汇编代码。要查看java方法jit编译后的汇编代码,我们不仅需要在执行java命令时指定一些参数,还需要额外的一个小工具来辅助我们对汇编代码进行反汇编。如果没有这个工具,jvm的输出是机器码,不可读。有了这个工具,它就可以帮助我们自动将机器码转为汇编代码,非常方便。这个工具是hsdis,它的源代码在jdk中,但是构建jdk的过程中不会构建这个工具。如果我们要使用它,我们必须单独构建它。从上图可以看出,该工具非常简单。主要是通过调用gnu的binutils对jvm输出的汇编代码进行解码。工具的详细构建过程请参考README和Makefile。因为这个工具依赖gnubinutils解码,所以我们需要先下载binutils:下载完binutils后,我们执行以下命令开始构建hsdis:$makeBINUTILS=binutils-2.35.1all64如果没有问题,最终会在build/linux-amd64目录下生成一个hsdis-amd64.so文件:将这个文件复制到我们之前搭建的jdk中:OK,准备工作已经完成,现在我们可以通过指定一些参数来查看java方法的汇编代码.我们仍然使用上面的java类T.java,假设我们想查看JIT编译后的方法f1的汇编代码,我们可以使用如下命令:这个命令会输出很多内容,下图中的是whatwewant:看到没有,真的是汇编,选中的那行是方法f1的加法逻辑。我们可以使用不同的参数来指定某个方法或者方法来查看,也可以使用-XX:+PrintAssembly参数来查看jit编译出来的所有方法。各个参数的使用和含义可以参考以下链接:https://docs.oracle.com/en/java/javase/15/docs/specs/man/java.html查看java的汇编代码方法,对于我们理解java的内部实现是非常有意义的。借助这个方法,我们可以理解文档中很多看不懂的内容,比如volatile。本文转载自微信公众号“猫食猫客”,可通过以下二维码关注。转载本文请联系猫猫猫客公众号。
