您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關怎么理解Java 執行過程中的內存模型變化,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
主要工作:嘗試以時間順序追蹤一遍 Java 執行的整個過程,以及展示 JVM 中內存模型的相應變化。
主要目的:希望能夠通過 Java 執行過程的冰山一角,增進對編程語言工作原理的理解。
以下面這段代碼為例,追蹤它的執行過程:
public class Car {
private int speed;
public void setSpeed(int speed) {
this.speed = speed;
}
public void getSpeed() {
System.out.println(speed);
}
public static void main(String[] args) {
Car car = new Car();
car.setSpeed(3);
car.getSpeed();
}
}
接下來是具體的執行過程,總共包含五個步驟:編譯、加載、執行 main 方法、執行成員方法、方法返回。
Step1:編譯
首先,在我們完成上述這段源碼之后,要想讓程序跑起來,我們需要將其編譯成為字節碼文件。字節碼是一種跨平臺的JVM機器語言,它能夠被JVM所解析,而無關底層的操作系統。
Step2:加載
當代碼需要被調用時,JVM 會加載目標字節碼至方法區,并轉化為方法區的運行時數據結構,這里的加載過程是通過類加載器完成的。然后內存中(不一定是堆)會生成一個代表這個類的 java.lang.Class 對象,作為方法區這個類的各種數據結構的訪問入口。
Step3:執行 main 方法
main 方法可以通過 java.lang.Class 對象進行調用,參考如下代碼:
Method method = targetClass.getDeclareMethod("main", String[].class);
method.invoke(null, (Object) new String[0]);
之后 PC 寄存器將會指向方法區中的 main 函數地址,線程棧中會生成對應的棧楨,其主要用于存放當前方法的局部變量表、操作棧、以及方法返回地址。接下來,PC 寄存器向后地址偏移,執行引擎開始執行 main 方法體。當語句 Car car = new Car() 執行完畢,棧楨與堆中的相應變化如下:
Step4:執行成員方法
對象 car 的 setSpeed 方法調用過程和 main 類似,通過索引 car 的成員方法地址,PC寄存器將指向方法區中的 setSpeed 函數地址,同時線程棧中將產生新的棧楨,其中的方法返回地址用于保存原有 PC 地址偏移。當賦值語句 this.speed = speed 執行完畢,棧楨與堆中發生的相應變化如下:
Step5:方法返回
隨著 setSpeed 方法的執行結束,Stack 中的相應棧楨出棧,棧頂指針重新指向 main 棧楨。同時 PC 寄存器將根據方法返回地址進行還原,從而繼續執行 main 的方法體。當 main 方法也執行完畢出棧后,主線程與虛擬機實例銷亡,程序結束。
虛擬機或某一門程序語言,作為一種底層實現,可以滿足上層用戶的絕大部分需求,但是需求是與時俱進的,總有一天用戶需要編寫自己的底層實現,比如組件、框架、一門新語言。這時需要打開原有的規范,先破壞它,再重建它,從而定義自己的規范。這也許是我們需要探究底層的緣由之一吧。
看完上述內容,你們對怎么理解Java 執行過程中的內存模型變化有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。