細說虛擬機器棧,細說虛擬機器
文章出自 http://www.mynawang.com/ 引文
對JVM不瞭解的請先訪問文章《Java虛擬機器運行時資料區》,相信會讓你大致瞭解各個記憶體地區的對應功能。接著,我們開始細說虛擬機器棧 前文中說到:“虛擬機器棧是線程私人的,每建立一個線程,虛擬機器就會為這個線程建立一個虛擬機器棧,虛擬機器棧表示Java方法執行的記憶體模型,每調用一個方法就會為每個方法產生一個棧幀(Stack Frame),用來儲存局部變數表、運算元棧、動態連結、方法出口等資訊。每個方法被調用和完成的過程,都對應一個棧幀從虛擬機器棧上入棧和出棧的過程。虛擬機器棧的生命週期和線程是相同的”。
虛擬機器棧
其中,虛擬機器棧是一個後入先出的棧。棧幀是儲存在虛擬機器棧中的,棧幀是用來儲存資料和儲存部分過程結果的資料結構,同時也被用來處理動態連結(Dynamic Linking)、方法傳回值和異常指派(Dispatch Exception)。線程運行過程中,只有一個棧幀是處於活躍狀態,稱為“當前活躍棧幀”,當前活動棧幀始終是虛擬機器棧的棧頂元素。如所示:
棧幀
上述內容已對棧幀做了大致介紹,接下去仔細描述棧幀中的運算元棧,動態串連,方法返回地址和一些額外的附加資訊。 如所示:
1.局部變數表
局部變數表是一組局部變數值儲存空間,用於存放方法參數和方法內部定義的局部變數。在Java檔案編譯為Class檔案時,就在方法表的Code屬性的max_locals資料項目中確定了該方法需要分配的最大局部變數表的容量。
2.運算元棧
運算元棧也常被稱為操作棧,它是一個後入先出棧。JVM底層位元組碼指令集是基於棧類型的,所有的作業碼都是對運算元棧上的資料進行操作,對於每一個方法的調用,JVM會建立一個運算元棧,以供計算使用。和局部變數一樣。運算元棧的最大深度也是編譯的時候寫入到方法表的code屬性的max_stacks資料項目中。運算元棧的每一個元素可以是任意的Java資料類型,包括long、double。32位元據類型所佔的棧容量為1,64位元據類型所佔的棧容量為2。棧容量的單位為“字寬”,對於32位虛擬機器來說,一個“字寬”佔4個位元組,64位虛擬機器來說,一個“字寬”佔8個位元組。當一個方法剛剛執行的時候,這個方法的運算元棧是空的,在方法執行的過程中,會有各種位元組碼指向運算元棧中寫入和提取值,也就是入棧與出棧操作。例如,在做算術運算的時候就是通過運算元棧來進行的,又或者調用其它方法的時候是通過運算元棧來行參數傳遞的。 另外,在概念性模型中,兩個棧幀作為虛擬機器棧的元素,相互之間是完全獨立的,但是大多數虛擬機器的實現裡都會作一些最佳化處理,令兩個棧幀出現一部分重疊。讓下棧幀的部分運算元棧與上面棧幀的部分局部變數表重疊在一起,這樣在進行方法調用返回時就可以共用一部分資料,而無須進行額外的參數複製傳遞了。
3.動態串連
每個棧幀都包含一個指向運行時常量池中該棧幀所屬性方法的引用,持有這個引用是為了支援方法調用過程中的動態串連。在Class檔案的常量池中存有大量的符號引用,位元組碼中的方法調用指令就以常量池中指向方法的符號引用為參數。這些符號引用一部分會在類載入階段或第一次使用的時候轉化為直接引用,這種轉化稱為靜態解析。另外一部分將在每一次的運行期期間轉化為直接引用,這部分稱為動態串連。
4.方法返回地址
當一個方法被執行後,有兩種方式退出這個方法。第一種方式是執行引擎遇到任意一個方法返回的位元組碼指令,這時候可能會有傳回值傳遞給上層的方法調用者(調用當前方法的的方法稱為調用者),是否有傳回值和傳回值的類型將根據遇到何種方法返回指令來決定,這種退出方法方式稱為正常完成出口(Normal Method Invocation Completion)。另外一種退出方式是,在方法執行過程中遇到了異常,並且這個異常沒有在方法體內得到處理,無論是Java虛擬機器內部產生的異常,還是代碼中使用athrow位元組碼指令產生的異常,只要在本方法的異常表中沒有搜尋到匹配的異常處理器,就會導致方法退出,這種退出方式稱為異常完成出口(Abrupt Method Invocation Completion)。一個方法使用異常完成出口的方式退出,是不會給它的調用都產生任何傳回值的。 無論採用何種方式退出,在方法退出之前,都需要返回到方法被調用的位置,程式才能繼續執行,方法返回時可能需要在棧幀中儲存一些資訊,用來協助恢複它的上層方法的執行狀態。一般來說,方法正常退出時,調用者PC計數器的值就可以作為返回地址,棧幀中很可能會儲存這個計數器值。而方法異常退出時,返回地址是要通過異常處理器來確定的,棧幀中一般不會儲存這部分資訊。 方法退出的過程實際上等同於把當前棧幀出棧,因此退出時可能執行的操作有:恢複上層方法的局部變數表和運算元棧,把傳回值(如果有的話)壓入調用都棧幀的運算元棧中,調用PC計數器的值以指向方法調用指令後面的一條指令等。
5.附加資訊
虛擬機器規範允許具體的虛擬機器實現增加一些規範裡沒有描述的資訊到棧幀中,例如與高度相關的資訊,這部分資訊完全取決於具體的虛擬機器實現。在實際開發中,一般會把動態串連,方法返回地址與其它附加資訊全部歸為一類,稱為棧幀資訊。