JVM內存模型如上圖所示.但是運行時方法在java代碼運行時是如何運轉的呢.下面我們通過一個簡單的代碼來看看運行時方法區的各個模塊是如何運轉的
package com.bonc.jvm;
/**
* @Classname JVMTest
* @Description TODO
* @Date 2020/6/14 10:54
* @Created by sz
*/
public class JVMTest {
public static User user = new User();
private final static int initData=1111;
public int computer(){
int a =1;
int b= 2;
int c=(a+b)*15;
return c;
}
public static void main(String[] args) {
JVMTest jvmTest =new JVMTest();
int computer = jvmTest.computer();
System.out.println(computer);
}
}
通過java自帶的javap -c命令可以查看編譯完,我們稍微可以理解的代碼
Compiled from "JVMTest.java"
public class com.bonc.jvm.JVMTest {
public static com.bonc.jvm.User user;
public com.bonc.jvm.JVMTest();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public int computer();
Code:
0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iload_1
5: iload_2
6: iadd
7: bipush 15
9: imul
10: istore_3
11: iload_3
12: ireturn
public static void main(java.lang.String[]);
Code:
0: new #2 // class com/bonc/jvm/JVMTest
3: dup
4: invokespecial #3 // Method "<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #4 // Method computer:()I
12: istore_2
13: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
16: iload_2
17: invokevirtual #6 // Method java/io/PrintStream.println:(I)V
20: return
static {};
Code:
0: new #7 // class com/bonc/jvm/User
3: dup
4: invokespecial #8 // Method com/bonc/jvm/User."<init>":()V
7: putstatic #9 // Field user:Lcom/bonc/jvm/User;
10: return
}
java 虛擬機運行一個線程會給當前線程分配一個棧空間.棧空間是有許多棧幀組成.每執行一個方法會給單前方法分配一個棧幀空間.棧幀空間有局部變量表,操作數棧,動態鏈接,方法出口.操作數棧:是指方法執行時臨時存放操作數的內存空間.
我們先看一下方法computer的反彙編代碼
執行完第一個反彙編代碼.查看操作手冊代碼 JVM指令手冊下載地址:傳送門
執行完computer內存空間爲
執行完istore_1 查看手冊這裏的局部變量1值得是局部變量表中第一個局部變量.也就是a
所以執行完這幾行代碼的結果爲
下面的 2: iconst_2 3: istore_2 這兩行代碼執行完之後內存空間的
下面執行iload_1查指令手冊
將局部變量表局部變量1放入操作數棧中
同理執行iload_2 將局部變量表局部變量2放入操作數棧中
所以至此jvm內存空間中的東西變成
執行6: iadd 查指令手冊 執行int類型的加法
將操作數棧中的變量拿到cpu中做加法算法,將執行結果重新壓回操作數棧中
所以執行結果爲
執行下一步bipush 15 查指令手冊
也就是將15壓入操作數棧中
接下來執行imul 查指令手冊
也就是將操作數棧中的數字拿到cpu中執行乘法,執行結果返回到操作數棧中
下面一步執行istore_3 和前面將操作數棧中的值45存入局部變量3中
再接着執行iload_3 查指令手冊
講局部變量表中局部變量3的數值加載到操作數棧中
再執行ireturn
將操作數棧中的值.作爲方法返回值返回