Java 執(zhí)行過程中的內(nèi)存模型
點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號(hào)”
優(yōu)質(zhì)文章,第一時(shí)間送達(dá)
? 作者?|? 小z同學(xué)
來(lái)源 |? urlify.cn/BF7zui
76套java從入門到精通實(shí)戰(zhàn)課程分享
一、前言
本文的主要工作:嘗試以時(shí)間順序追蹤一遍 Java 執(zhí)行的整個(gè)過程,以及展示 JVM 中內(nèi)存模型的相應(yīng)變化。
本文的主要目的:希望能夠通過 Java 執(zhí)行過程的冰山一角,增進(jìn)對(duì)編程語(yǔ)言工作原理的理解。
以下面這段代碼為例,追蹤它的執(zhí)行過程:
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();
????}
}
二、執(zhí)行過程
接下來(lái)是具體的執(zhí)行過程,總共包含五個(gè)步驟:編譯、加載、執(zhí)行 main 方法、執(zhí)行成員方法、方法返回。
Step1:編譯
首先,在我們完成上述這段源碼之后,要想讓程序跑起來(lái),我們需要將其編譯成為字節(jié)碼文件。字節(jié)碼是一種跨平臺(tái)的JVM機(jī)器語(yǔ)言,它能夠被JVM所解析,而無(wú)關(guān)底層的操作系統(tǒng)。
Step2:加載
當(dāng)代碼需要被調(diào)用時(shí),JVM 會(huì)加載目標(biāo)字節(jié)碼至方法區(qū),并轉(zhuǎn)化為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu),這里的加載過程是通過類加載器完成的。然后內(nèi)存中(不一定是堆)會(huì)生成一個(gè)代表這個(gè)類的 java.lang.Class 對(duì)象,作為方法區(qū)這個(gè)類的各種數(shù)據(jù)結(jié)構(gòu)的訪問入口。

Step3:執(zhí)行 main 方法
main 方法可以通過 java.lang.Class 對(duì)象進(jìn)行調(diào)用,參考如下代碼:
Method?method?=?targetClass.getDeclareMethod("main",?String[].class);
method.invoke(null,?(Object)?new?String[0]);
之后 PC 寄存器將會(huì)指向方法區(qū)中的 main 函數(shù)地址,線程棧中會(huì)生成對(duì)應(yīng)的棧楨,其主要用于存放當(dāng)前方法的局部變量表、操作棧、以及方法返回地址。接下來(lái),PC 寄存器向后地址偏移,執(zhí)行引擎開始執(zhí)行 main 方法體。當(dāng)語(yǔ)句 Car car = new Car() 執(zhí)行完畢,棧楨與堆中的相應(yīng)變化如下:

Step4:執(zhí)行成員方法
對(duì)象 car 的 setSpeed 方法調(diào)用過程和 main 類似,通過索引 car 的成員方法地址,PC寄存器將指向方法區(qū)中的 setSpeed 函數(shù)地址,同時(shí)線程棧中將產(chǎn)生新的棧楨,其中的方法返回地址用于保存原有 PC 地址偏移。當(dāng)賦值語(yǔ)句 this.speed = speed 執(zhí)行完畢,棧楨與堆中發(fā)生的相應(yīng)變化如下:

Step5:方法返回
隨著 setSpeed 方法的執(zhí)行結(jié)束,Stack 中的相應(yīng)棧楨出棧,棧頂指針重新指向 main 棧楨。同時(shí) PC 寄存器將根據(jù)方法返回地址進(jìn)行還原,從而繼續(xù)執(zhí)行 main 的方法體。當(dāng) main 方法也執(zhí)行完畢出棧后,主線程與虛擬機(jī)實(shí)例銷亡,程序結(jié)束。
三、雜談
虛擬機(jī)或某一門程序語(yǔ)言,作為一種底層實(shí)現(xiàn),可以滿足上層用戶的絕大部分需求,但是需求是與時(shí)俱進(jìn)的,總有一天用戶需要編寫自己的底層實(shí)現(xiàn),比如組件、框架、一門新語(yǔ)言。這時(shí)需要打開原有的規(guī)范,先破壞它,再重建它,從而定義自己的規(guī)范。這也許是我們需要探究底層的緣由之一吧。
粉絲福利:Java從入門到入土學(xué)習(xí)路線圖
??????

??長(zhǎng)按上方微信二維碼?2 秒
感謝點(diǎn)贊支持下哈?
