java虚拟机栈
虚拟机栈存储内容
栈帧
每个栈帧对应一个被调用的方法,可理解为一个方法的运行空间。
Local Variables 局部变量表
方法中定义的局部变量及方法的参数
局部变量表中的变量不可直接使用,如需使用,必须通过相关指令将其加载至操作数栈中作为操作数使用。
局部变量表在编译器就已经确定大小了,因为局部变量的类型和个数在编译器就已确定。
Operand Stacks 操作数栈
以入栈和出栈方式存储操作数
Dynamic Linking 动态链接
每个栈帧都包含一个执行运行时常量池中该栈帧所属方法的引用。
持有这个引用是为了支持方法调用过程中的动态连接(Dynamic Linking)
Invocation/Completion 方法返回地址
当一个方法开始执行后,只有两种方式可以退出,
一种是遇到方法返回的字节码指令;
一种是遇见异常,并且这个异常没有在方法体内得到处理。
例子
class Person{
private String name="Jack";
private int age;
private final double salary=100;
private static String address;
private final static String hobby="Programming";
public void say(){
System.out.println("person say...");
}
public static int calc(int op1,int op2){
op1=3;
int result=op1+op2;
return result;
}
public static void order(){
}
public static void main(String[] args){
calc(1,2);
order();
}
}
对java文件进行分析
- 对Person.java 编译
javac Person.java 生成Person.class
- 对Person.class进行反编译
javap -c Person.class
- 截图如下
对calc()方法分析
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.iconst_i
public static int calc(int op1,int op2){
op1=3;
int result=op1+op2;
return result;
}
calc()中的局部变量为op1,op2,result 对应到局部变量表中
public static int calc(int, int);
Code:
0: iconst_3 //Push int constant 把int常量值3push到操作数栈中
1: istore_0 //Store int into local variable 把3存储到局部变量0中-->弹出操作数栈赋值给局部变量0
2: iload_0 //Load int from local variable 从局部变量表里加载局部变量0到操作数栈
3: iload_1 //Load int from local variable 从局部变量表里加载局部变量1到操作数栈
4: iadd //Add int 将上述两个值弹出栈进行相加,结果push回操作数栈
5: istore_2 //Store int into local variable 将栈顶int值保存到局部变量2中
6: iload_2 //Load int from local variable 从局部变量表里加载局部变量2到操作数栈
7: ireturn //Return int from method 从方法中返回int类型的数据