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類型的數據