摘要:對于執(zhí)行引擎來說,在活動線程中,只有位于棧頂?shù)臈攀亲钣行У姆Q為當(dāng)前棧幀與這個棧幀相關(guān)聯(lián)的方法稱為當(dāng)前方法。執(zhí)行引擎運行的所有的字節(jié)碼指令都只針對當(dāng)前棧幀進(jìn)行操作。
棧幀數(shù)據(jù)結(jié)構(gòu)
棧幀(Stack Frame)是用來支持虛擬機進(jìn)行方法調(diào)用和方法執(zhí)行的數(shù)據(jù)結(jié)構(gòu),它是虛擬機運行時數(shù)據(jù)區(qū)中的虛擬機棧的棧元素。
棧幀(Stack Frame)存儲了方法的局部變量表、操作數(shù)棧、動態(tài)連接、和方法返回地址、額外的附加信息。
每個方法在執(zhí)行的同時,都會創(chuàng)建一個棧幀(Stack Frame)。每一個方法從調(diào)用開始至執(zhí)行完成的過程,都對應(yīng)著一個棧幀在虛擬機棧里面從入棧到出棧的過程。
棧幀的內(nèi)存分配在編譯程序代碼的時候,棧幀中需要多大的局部變量表,多深的操作數(shù)棧都已經(jīng)完全確定了,并且寫入到方法表的Code屬性中了,因此一個棧幀需要分配多少內(nèi)存,不會受到程序運行期變量數(shù)據(jù)的影響,而僅僅取決于具體虛擬機的實現(xiàn)。
當(dāng)前棧幀(Current Stack Frame)一個線程中的方法調(diào)用鏈可能會很長,很多方法都同時處于執(zhí)行狀態(tài)。對于執(zhí)行引擎來說,在活動線程中,只有位于棧頂?shù)臈攀亲钣行У?稱為當(dāng)前棧幀(Current Stack Frame),與這個棧幀相關(guān)聯(lián)的方法稱為當(dāng)前方法。執(zhí)行引擎運行的所有的字節(jié)碼指令都只針對當(dāng)前棧幀進(jìn)行操作。在概念模型上,典型的棧幀結(jié)構(gòu)圖如下:
局部變量表局部變量表(Local Variable Table)是一組變量值存貯空間,用于存放方法參數(shù)和方法內(nèi)定義的局部變量。在Java程序編譯為Class文件時候,就在方法的Code屬性的max_locals數(shù)據(jù)項中確定了該方法所需要分配的局部變量表的最大容量。單位為Slot
局部變量表的容量以變量槽(Variable Slot)為最小單位。每個變量槽都可以存儲32位長度的內(nèi)存空間,例如boolean、byte、char、short、int、float、reference。
對于64位長度的數(shù)據(jù)類型(long,double),虛擬機會以高位對齊方式為其分配兩個連續(xù)的Slot空間,也就是相當(dāng)于把一次long和double數(shù)據(jù)類型讀寫分割成為兩次32位讀寫。
整型 | 字節(jié)(b) | bite(位) |
---|---|---|
byte | 1 | 1*8 |
short | 2 | 2*8 |
int | 4 | 4*8 |
long | 8 | 8*8 |
浮點型 | 字節(jié)(b) | bite(位) |
---|---|---|
float | 4 | 4*8 |
double | 8 | 8*8 |
char類型 | 字節(jié)(b) | bite(位) |
---|---|---|
char | 2 | 2*8 |
布爾型 | 字節(jié)(b) | bite(位) |
---|---|---|
boolean | 1 | 1*8 |
其中:8bit=1b [一個Byte等于8個bit(位)],1024b=1kb
為了節(jié)省棧幀空間,局部變量表中的Slot是可以重用的,方法體中定義的變量,其作用域并不一定會覆蓋整個方法體,如果當(dāng)前字節(jié)碼PC計數(shù)器的值已經(jīng)超過了某個變量的作用域,那么這個變量對應(yīng)的Slot就可以交給其他變量使用。
優(yōu)點 : 節(jié)省棧幀空間。
缺點 : 影響到系統(tǒng)的垃圾收集行為。(如大方法占用較多的Slot,執(zhí)行完該方法的作用域后沒有對Slot賦值或者清空設(shè)置null值,垃圾回收器便不能及時的回收該內(nèi)存。)
操作數(shù)棧(operand Stack)也常稱為操作棧,它是一個后入先出棧。和局部變量表一樣,操作數(shù)棧的最大深度也在編譯的時候?qū)懭氲紺ode屬性的max_stacks中。
操作數(shù)棧的每一個元素可用是任意的Java數(shù)據(jù)類型,包括long和double。32位數(shù)據(jù)類型所占的棧容量為1,64位數(shù)據(jù)類型占用的棧容量為2。
當(dāng)一個方法剛剛開始執(zhí)行的時候,這個方法的操作數(shù)棧是空的,在方法執(zhí)行的過程中,會有各種字節(jié)碼指令往操作數(shù)棧中寫入和提取內(nèi)容,也就是出棧 / 入棧操作。例如,在做算術(shù)運算的時候是通過操作數(shù)棧來進(jìn)行的,又或者在調(diào)用其它方法的時候是通過操作數(shù)棧來進(jìn)行參數(shù)傳遞的。
動態(tài)連接每個棧幀都包含一個指向運行時常量池中該棧幀所屬方法的引用,持有這個引用是為了支持方法調(diào)用過程中的動態(tài)連接(Dynamic Linking)。
Class文件的常量池中存在大量符號引用,字節(jié)碼中的方法調(diào)用指令就以常量池中指向方法的符號引用作為參數(shù),這些符號引用一部分在類加載階段中的解析階段會轉(zhuǎn)為直接引用,這種轉(zhuǎn)化也稱為靜態(tài)解析。另外的一部分將在每一次運行時期轉(zhuǎn)化為直接引用。這部分稱為動態(tài)連接。
方法返回地址當(dāng)一個方法開始執(zhí)行后,只有2種方式可以退出這個方法 :
方法返回指令 : 執(zhí)行引擎遇到一個方法返回的字節(jié)碼指令,這時候有可能會有返回值傳遞給上層的方法調(diào)用者,這種退出方式稱為正常完成出口。
異常退出 : 在方法執(zhí)行過程中遇到了異常,并且沒有處理這個異常,就會導(dǎo)致方法退出。
無論采用任何退出方式,在方法退出之后,都需要返回到方法被調(diào)用的位置,程序才能繼續(xù)執(zhí)行,方法返回時可能需要在棧幀中保存一些信。用來幫助恢復(fù)它的上層方法的執(zhí)行狀態(tài)。
方法退出的過程實際上就等于把當(dāng)前棧幀出棧,因此退出可能執(zhí)行的操作有:
1.恢復(fù)上層方法的局部變量表和操作數(shù)棧
2.把返回值(如果存在返回值)壓入調(diào)用者棧幀的操作數(shù)棧中
3.調(diào)整PC計數(shù)器的值以指向方法調(diào)用指令后面的一條指令
虛擬機規(guī)范允許具體的虛擬機實現(xiàn)增強一些規(guī)范里沒有描述的信息到棧幀之中,例如與調(diào)試相關(guān)的信息,這部分信息取決于具體的虛擬機實現(xiàn)。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/75883.html
摘要:在本文,筆者將與大家概覽的體系結(jié)構(gòu)與工作方式。將第條和第條指令分別是將兩個局部變量入棧,然后相加。最后一條指令是,這條指令執(zhí)行完后當(dāng)前的這個方法對應(yīng)的這些部件會被回收,局部變量區(qū)的所有值將全部釋放,寄存器會被銷魂,在棧中與這個方 Java之所以號稱一次編譯,到處運行,主要原因是JVM屏蔽了各個計算機平臺相關(guān)的軟件(大多指系統(tǒng))或者硬件之間的差異,使得與平臺相關(guān)的耦合統(tǒng)一由JVM提供者來...
摘要:每個棧幀中包括局部變量表用來存儲方法中的局部變量非靜態(tài)變量函數(shù)形參。操作數(shù)棧虛擬機的解釋執(zhí)行引擎被稱為基于棧的執(zhí)行引擎,其中所指的棧就是指操作數(shù)棧。指向運行時常量池的引用存儲程序執(zhí)行時可能用到常量的引用。 本篇文章轉(zhuǎn)自微信公眾號:Java后端技術(shù) 學(xué)過Java基礎(chǔ)的人都知道:值傳遞和引用傳遞是初次接觸Java時的一個難點,有時候記得了語法卻記不得怎么實際運用,有時候會的了運用卻解釋不出...
摘要:操作數(shù)棧虛擬機的解釋執(zhí)行引擎被稱為基于棧的執(zhí)行引擎,其中所指的棧就是指操作數(shù)棧。基本數(shù)據(jù)類型的靜態(tài)變量前面提到方法區(qū)用來存儲一些共享數(shù)據(jù),因此基本數(shù)據(jù)類型的靜態(tài)變量名以及值存儲于方法區(qū)的運行時常 本文旨在用最通俗的語言講述最枯燥的基本知識 學(xué)過Java基礎(chǔ)的人都知道:值傳遞和引用傳遞是初次接觸Java時的一個難點,有時候記得了語法卻記不得怎么實際運用,有時候會的了運用卻解釋不出原理,而...
摘要:虛擬機在執(zhí)行程序的過程中會把它所管理的內(nèi)存劃分為若干個不同的數(shù)據(jù)區(qū)域。棧幀棧幀是用于支持虛擬機進(jìn)行方法調(diào)用和方法執(zhí)行的數(shù)據(jù)結(jié)構(gòu),它是虛擬機運行時數(shù)據(jù)區(qū)中的虛擬機棧的棧元素。棧幀的概念結(jié)構(gòu)如下運行時數(shù)據(jù)區(qū)腦圖高 這里我們先說句題外話,相信大家在面試中經(jīng)常被問到介紹Java內(nèi)存模型,我在面試別人時也會經(jīng)常問這個問題。但是,往往都會令我比較尷尬,我還話音未落,面試者就會背誦一段(Java虛擬...
摘要:內(nèi)存模型首先介紹下程序具體執(zhí)行的過程源代碼文件后綴會被編譯器編譯為字節(jié)碼文件后綴由中的類加載器加載各個類的字節(jié)碼文件,加載完畢之后,交由執(zhí)行引擎執(zhí)行在整個程序執(zhí)行過程中,會用一段空間來存儲程序執(zhí)行期間需要用到的數(shù)據(jù)和相關(guān)信息,這段空間一般被 [TOC] JVM內(nèi)存模型 首先介紹下Java程序具體執(zhí)行的過程: Java源代碼文件(.java后綴)會被Java編譯器編譯為字節(jié)碼文件(....
閱讀 1294·2023-04-25 19:33
閱讀 1175·2021-10-21 09:39
閱讀 3648·2021-09-09 09:32
閱讀 2627·2019-08-30 10:58
閱讀 1618·2019-08-29 16:17
閱讀 881·2019-08-29 15:29
閱讀 2892·2019-08-26 11:55
閱讀 2664·2019-08-26 10:33