javap是jdk自带的反解析工具。它的作用就是根据class字节码文件,反解析出当前类对应的code区 (汇编指令)、本地变量表、异常表和代码行偏移量映射表、常量池等等信息。
当然这些信息中,有些信息(如本地变量表、指令和代码行偏移量映射表、常量池中方法的参数名称等等) 需要在使用javac编译成class文件时,指定参数才能输出,比如,你直接javac xx.java,就不会在 生成对应的局部变量表等信息,如果你使用javac -g xx.java就可以生成所有相关信息了。如果你使用的 eclipse,则默认情况下,eclipse在编译时会帮你生成局部变量表、指令和代码行偏移量映射表等信息的。
通过反编译生成的汇编代码,我们可以深入的了解java代码的工作机制。比如我们可以查看i++;这行代码 实际运行时是先获取变量i的值,然后将这个值加1,最后再将加1后的值赋值给变量i。
通过局部变量表,我们可以查看局部变量的作用域范围、所在槽位等信息,甚至可以看到槽位复用等信息。
指令格式
前提条件,本文使用的java版本如下:
$ java -version
java version "1.8.0_231"
Java(TM) SE Runtime Environment (build 1.8.0_231-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.231-b11, mixed mode)
通过 javap -help
可以看到所有可以使用的参数:
$ javap --help
用法: javap <options> <classes>
其中, 可能的选项包括:
-help --help -? 输出此用法消息
-version 版本信息
-v -verbose 输出附加信息
-l 输出行号和本地变量表
-public 仅显示公共类和成员
-protected 显示受保护的/公共类和成员
-package 显示程序包/受保护的/公共类
和成员 (默认)
-p -private 显示所有类和成员
-c 对代码进行反汇编
-s 输出内部类型签名
-sysinfo 显示正在处理的类的
系统信息 (路径, 大小, 日期, MD5 散列)
-constants 显示最终常量
-classpath <path> 指定查找用户类文件的位置
-cp <path> 指定查找用户类文件的位置
-bootclasspath <path> 覆盖引导类文件的位置
一般常用的是 -v
、-l
、-c
三个选项。
javap -v classxx
:不仅会输出行号、本地变量表信息、反编译汇编代码,还会输出当前类用到的常量池等信息。javap -l classxx
:会输出行号和本地变量表信息。javap -c classxx
:会对当前class字节码进行反编译生成汇编代码。
查看汇编代码时,需要知道里面的jvm指令,可以参考官方文档:The Java Virtual Machine Instruction Set
另外通过 jclasslib
工具也可以看到上面这些信息,而且是可视化的,效果更好一些。
开始写作吧
![image-alter](/image/post/2021/08/22/01/xxx.jpg)
参考资料
文档信息
- 本文作者:Bob.Zhu
- 本文链接:https://adolphor.github.io/2021/08/22/01-jvm-javap/
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)