Javap简介
javap可以用来查看java编译器生成的字节码。通过它,我们可以深入的了解java代码的工作机制。它是JDK自带的反汇编器,你可以在jdk的bin中你可以找到它。在你正确配置了java环境后,就可以在命令窗口使用javap。列如:
或者你想方便点,那可以在你的IDE中配置,IDEA配置javap
当然其他的插件也很多,也可以供选择,网上很多。
Javap使用
javap使用的格式:javap <options> <classes>
<options>
命令选项一般用-c,-v比较多。-v显示的信息包含-c,-c简洁直观,-v显示的附加信息比较多。
javap -c classes:对当前class字节码反编译,生成汇编代码。
javap -v classes:不仅会输出行号、本地变量表信息、反编译汇编代码,还会输出当前类用到的常量池等信息。
<classes>
可以是一个或多个class文件,多个要用空格分隔。如:
Javap实例
public class test2 {
public static void main(String[] args) {
int i = 1;
int j = i + 2;
}
}
public class test2 {
public test2();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_1
1: istore_1
2: iload_1
3: iconst_2
4: iadd
5: istore_2
6: return
}
我们来看下这些都是什么意思
默认构造函数内:
0: aload_0 从本地变量表中加载变量0的值,即this的引用,入栈
1: invokespecial #1 出栈,调用java/lang/Object.""😦)V 初始化对象,就是this指定的对象的init()方法完成初始化
main函数内:
0: iconst_1,表示将int型1压入栈。0:表示执行的顺序,i表示int型,_1中的1代表压栈的值,如:iconst_2,即把int型数值2压入栈。
1: istore_1,表示将栈顶的值放入变量1 中,即i,_1代表变量的序列,如:istore_2就是为变量2赋值。
2: iload_1,将变量1 即 i 的的值放入栈顶。iload是从变量压入栈,iconst是常量压入栈。
4: iadd, 2个数出栈 相加,然后再入栈。
这边再提供一些地址供大家参考
JVM字节码指令简介
整理的Java字节码指令收集大全
Javap官网
Javap官网字节码
PS 之所以看javap,要从那个中午说起。。。
唉,我也答错了(菜)。答案是4,1,11。我本以为k = 4 + 3 * 3=13,实际它是 k = 2 + 3 * 3。基础不牢固,编码泪两行。
public static void main(java.lang.String[]);
Code:
0: iconst_1
1: istore_1
2: iload_1
3: iinc 1, 1 // 变量i自增为2,但是操作数栈中值不受影响,还是1
// iinc 1, 1 将变量1 的值加1,第一个1是序列,第二个是值
6: istore_1 // 操作数栈中值赋给i, i=1
7: iload_1 // 变量i 入栈,栈顶值为1
8: iinc 1, 1 // 局部变量i = 2
11: istore_2 // int j = 1
12: iload_1 // 变量i入栈,栈里的值:2
13: iinc 1, 1 // 这边是++i, 变量i自增,i=3
16: iload_1 // i=3入栈,栈中:3,2。13和16步说明++i是先自增后赋值
17: iload_1 // i=3入栈,栈中是3,3,2
18: iinc 1, 1 // i++, i=4,17,18步说明i++是先赋值后自增
21: imul // 取出栈中2个数相乘,即3*3。再入栈,栈中是9,2
22: iadd // 9+2,栈中11
23: istore_3 // int k = 11
24: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
27: iload_1
28: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
31: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
34: iload_2
35: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
38: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
41: iload_3
42: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
45: return
}
最后,