1、初始javap,通过javap命令查看程序计数器、局部变量表,操作数栈变化。
public class TestZhaZhaJavap {
public int test() {
int a=100;
int b=200;
int c=300;
return (a+b)*c;
}
}
a、图A标明当指令偏移到12时候当前局部变量和操作数栈变化情况
b、图B,标明执行完iadd指令后当前存在的操作数栈顶信息。
c、同样当执行到偏移地址为15的指令时:将操作数栈顶数据做乘法后重新放入栈顶,遇到ireturn 返回栈顶数据。
2、javap -c 查看class 文件字节码信息,解决 finally是在try方法块return后执行还是return之前执行
public class TestZhaZhaHaoException {
public static void main(String[] args) {
int t=t();
System.out.println(t);
}
public static int t(){
int i=1;
try {
return i;
} finally {
++i;
}
}
}
使用javap -c 查看TestZhaZhaHaoException 字节文件,输出结果如一下截图:
同时由字节码可见finally是在return执行返回之前执行。
3、class 文件部分指令解析
与方法相关的JVM指令:
指令 | 操作数 | 解释 |
invokeinterface | class/method desc | 调用接口方法 |
invokespecial | class/method desc | 调用超类构造方法、实例初始化方法或私有方法 |
invokestatic | class/method desc | 调用静态方法 |
invokevirtual | class/method desc | 调用实例方法 |
dup:将当前栈顶元素复制一份,并压入战中。
pop:从当前栈顶出栈一个元素。
pop2:从栈顶的一个long或double类型的或两个其他数据从栈顶弹出
swap:将栈顶两个非long或者double类型的数值交换
指令 | 操作数 | 解释 |
aload | n | 将当前本地变量n放入栈顶中,变量n是一个引用,如aload_1,aload_2,aload_3 |
astore | n | 将栈顶元素存入本地变量n中,变量n是一个引用 |
dload | n | 将当前本地变量n放入栈顶中,变量n是一个double类型 |
dstore | n | 将栈顶元素存入本地变量n中,变脸n是一个double类型 |
fload | n | 将当前本地变量n放入栈顶中,变量n是一个fload类型 |
fstore | n | 将栈顶元素存入本地变量n中,变量n是一个float类型 |
iinc | n increment | 将指定int型变量增加指定值 |
iload | n | 将当前本地变量n放入栈顶中,变量n是一个int类型 |
lload | n | 将当前本地变量n放入栈顶中,变量n是一个long类型 |
istore | n | 将栈顶元素存入本地变量n中,变量n是一个long类型 |
指令解释参照:https://blog.youkuaiyun.com/fouy_yun/article/details/78010952