javap
是JDK自带的反汇编器,可以用于查看Java编译器对Java源代码编译后,生成的字节码(ByteCode)中的详细信息。
换句话来说,javap
相当于一个分解工具。使用它可以让我们更清晰的看到字节码内部包含什么东西。
同样,通过对照源代码和字节码,我们也可以了解更多关于编译器内部的工作机制。
一.参数含义
下文会用例子以对这些参数的含义进行详细介绍:
1.用法
javap <options> <classes>...
2.options可以包含的参数
(1) -help
--help
-?
官方解释:Print this usage message 意义:帮助
(2)-version
官方解释:Version information 意义:显示当前.class基于哪个JDK版本编译
(3) -v
-verbose
官方解释:Print additional information 意义:输出额外信息(堆栈大小、各方法的locals及args参数,以及class文件的编译版本)
(4) -l
官方解释:Print line number and local variable tables 意义:输出行、局部变量表
(5)-public
官方解释:Show only public classes and members 意义:只显示public类及成员
(6)-protected
官方解释:Show protected/public classes and members 意义:只显示protected和public类及成员
(7)-package
官方解释:Show package/protected/public classes and members (default) 意义:只显示包、protected和public类及成员(这是缺省设置)
(8)-p
-private
官方解释:Show all classes and members 意义:显示所有的类和成员
(9)-c
官方解释:Disassemble the code 意义:反汇编方法内部实现对应的字节码
(10)-s
官方解释:Print internal type signatures
(11)-sysinfo
官方解释:Show system info (path, size, date, MD5 hash) of class being processed
(12)-constants
官方解释:Show final constants 意义:显示所有final修饰的常量
(13) -classpath <path>
官方解释:Specify where to find user class files
(14)-cp <path>
官方解释:Specify where to find user class files
(15)-bootclasspath <path>
官方解释:Override location of bootstrap class files
二.源代码:
后文的参数解读,均基于此源代码(HelloWorld.java)编译出的字节码(HelloWorld.class)进行分析。
public class HelloWorld {
private static final int P_1 = 1;
public static final int P_2 = 2;
public String publicString;
private String privateString;
public static void main(String[] args){
System.out.println("Hello World!");
}
protected void protectedMethod(){
System.out.println("protectedMethod!");
}
private void privateMethod(){
System.out.println("privateMethod!");
}
}
二.参数解读
1.默认参数(-package):
javap HelloWorld.class
// 等效于以下(即 只显示包、protected和public类及成员)
javap -package HelloWorld.class
注意:
- 只有方法声明,没有方法具体实现对应的字节码汇编代码
- private方法和字段不会被显示
2.方法和字段的显示控制参数
以下四个参数均是控制要显示的方法和字段的范围:
// 只显示public类及成员
-public Show only public classes and members
// 只显示protected和public类及成员
-protected Show protected/public classes and members
// 只显示包、protected和public类及成员(这是缺省设置)
-package Show package/protected/public classes
and members (default)
// 显示所有的类和成员
-p -private Show all classes and members
(1)-public
javap -public HelloWorld.class
注意:
- 只有方法声明,没有方法具体实现对应的字节码汇编代码
- 只有 public 方法和字段会被显示
(2)-private
javap -private HelloWorld.class
注意:
- 只有方法声明,没有方法具体实现对应的字节码汇编代码
- public、protected、private 方法和字段都会被显示
3.-c
显示方法内部实现对应的字节码汇编代码
-c
用于显示方法内部实现对应的字节码汇编代码
javap -c HelloWorld.class
4.-l
显示字节码代码与源代码的行号映射关系
javap -l HelloWorld.class
在源代码编译成字节码的过程中,编译器会生成一个源代码与源代码编译后的字节码的行号映射表。
这样,当在动态断点调试代码时,IDE就可以将当前运行到的二进制代码与对应源代码关联起来,最终在IDE上显示。
类似的行号映射表:
-
Objective-C 如果你做过iOS开发,并学习过Objective-C,那么你将很容易理解,
-l
显示的信息与.dSYM
文件中存储的信息的作用是类似的。 -
TypeScript、Dart、CoffeeScript等 如果你使用过TypeScript、Dart、CoffeeScript等最终编译成JavaScript的语言,在编译时,可选择生成一个.map文件,这个
.map
文件中存储的信息与-l
显示的信息作用是也是类似的。
5.-constants
显示被修饰为final的静态常量
javap -constants HelloWorld.class
6.-v
-verbose
输出额外信息(堆栈大小、各方法的locals及args参数,以及class文件的编译版本)
javap -v HelloWorld.class
7.sysinfo
显示当前.class的系统信息 (路径, 大小, 日期, MD5 )
javap -sysinfo HelloWorld.class
8.-s
输出内部类型签名
javap -s HelloWorld.class