1. 程式人生 > >Java 執行過程中的記憶體模型

Java 執行過程中的記憶體模型

#### 一、前言 **本文的主要工作**:嘗試以時間順序追蹤一遍 Java 執行的整個過程,以及展示 JVM 中記憶體模型的相應變化。 **本文的主要目的**:希望能夠通過 Java 執行過程的冰山一角,增進對程式語言工作原理的理解。 以下面這段程式碼為例,追蹤它的執行過程: ```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 物件,作為方法區這個類的各種資料結構的訪問入口。 ![](https://img2020.cnblogs.com/blog/1039974/202101/1039974-20210131182548437-1656820007.png) **Step3**:執行 main 方法 main 方法可以通過 java.lang.Class 物件進行呼叫,參考如下程式碼: ```java Method method = targetClass.getDeclareMethod("main", String[].class); method.invoke(null, (Object) new String[0]); ``` 之後 PC 暫存器將會指向方法區中的 main 函式地址,執行緒棧中會生成對應的棧楨,其主要用於存放當前方法的區域性變量表、操作棧、以及方法返回地址。接下來,PC 暫存器向後地址偏移,執行引擎開始執行 main 方法體。當語句 Car car = new Car() 執行完畢,棧楨與堆中的相應變化如下: ![](https://img2020.cnblogs.com/blog/1039974/202101/1039974-20210131182615986-268099081.png) **Step4**:執行成員方法 物件 car 的 setSpeed 方法呼叫過程和 main 類似,通過索引 car 的成員方法地址,PC暫存器將指向方法區中的 setSpeed 函式地址,同時執行緒棧中將產生新的棧楨,其中的方法返回地址用於儲存原有 PC 地址偏移。當賦值語句 this.speed = speed 執行完畢,棧楨與堆中發生的相應變化如下: ![](https://img2020.cnblogs.com/blog/1039974/202101/1039974-20210131182635313-809201412.png) **Step5**:方法返回 隨著 setSpeed 方法的執行結束,Stack 中的相應棧楨出棧,棧頂指標重新指向 main 棧楨。同時 PC 暫存器將根據方法返回地址進行還原,從而繼續執行 main 的方法體。當 main 方法也執行完畢出棧後,主執行緒與虛擬機器例項銷亡,程式結束。 #### 三、雜談 虛擬機器或某一門程式語言,作為一種底層實現,可以滿足上層使用者的絕大部分需求,但是需求是與時俱進的,總有一天使用者需要編寫自己的底層實現,比如元件、框架、一門新語言。這時需要開啟原有的規範,先破壞它,再重建它,從而定義自己的規範。這也許是我們需要探究底層的緣由之一吧。
**參考連結** [1] <<深入理解Java虛擬機器>> [2] [https://www.cnblogs.com/zzzz76/p/9282981.html](https://www.cnblogs.com/zzzz76/p/9282981.html) [3] [https://www.cnblogs.com/zzzz76/p/8150862.html](https://www.cnblogs.com/zzzz76/p/8150862.html) [4] [https://www.cnblogs.com/zzzz76/p/8076536.html](https://www.cnblogs.com/zzzz76/p/80765