虛擬機棧的棧幀都包含些什麼?

一、虛擬機執行引擎

虛擬機執行引擎是java虛擬機核心組成部分之一。虛擬機是相對於物理機的概念,他們都有代碼執行能力,區別在於物理機執行引擎直接建立在處理器、硬件指令集、操作系統層面,而虛擬機的執行引擎是由自己實現,用於執行虛擬機字節碼指令集。
執行引擎執行java代碼的時候可能有解釋執行(通過解釋器執行)和編譯執行(通過執行編譯器產生本地代碼執行)兩種方式,所有的java虛擬機執行引擎都是一致的,輸入的是字節碼文件,處理過程是字節碼解析的等效過程,輸出執行結果。

二、運行時棧幀結構

棧幀是用於支持虛擬機進行方法調用和方法執行的數據結構,它是虛擬街運行時數據區中的虛擬機棧的棧元素。棧幀存儲了方法的局部變量表操作數棧動態鏈接方法返回地址等信息。每一個方法從調用開始到執行完成的過程,都是一個棧幀在虛擬機棧裏面從出棧到入棧的過程。
關於棧幀:
棧幀中主要空間的局部變量表和操作數棧,而局部變量表和操作數棧的大小,在編譯期間就已經確定,不會收到運行期間變量數據的影響。
在活動線程中,只用位於棧頂的棧幀是有效的,也就是處於執行狀態,成爲當前棧幀。
下面看看棧幀中的各個存儲空間都有什麼用處。

1、局部變量表

局部變量表是一組變量值存儲空間,用於存放方法參數和方法內部定義的局部變量
局部變量表有以下特徵:

  • 局部變量表的容量以變量槽(Slot)爲最小單位,每個Slot都應該至少能存放一個boolean、byte、char、short、int、float、reference類型的數據。
  • reference數據類型稱爲引用類型,虛擬機可以通過此類型數據直接或間接地查找對象實例數據在java堆中的索引和對象所對應類在方法區中的類型信息。
  • 方法內部定義的變量存放在局部變量表中,稱爲局部變量。局部變量不像類變量那樣有加載過程中有準備階段,所有局部變量不會被被賦予默認初始值,必須手動賦值。

2、操作數棧

操作數棧也成爲操作棧,後入先出,操作數棧的最大深度也在編譯的時候就已經確定,不會在運行期間動態變化。32位數據類型所佔的棧容量爲1,64位數據類型所佔棧容量爲2.
方法在執行過程中,各種字節碼指令往操作數棧中寫入或提取內容,也就是入棧和出棧。比如執行iadd指令時,將操作數棧頂的兩個int型數值出棧並相加,然後將結果入棧。
java虛擬機的解釋執行引擎就是基於操作數棧的執行引擎。

3、動態連接

class文件的常量池中有大量的符號引用,字節碼中的方法調用指令就以常量池指向的方法的符號引用作爲參數。這些符號引用一部分會在類加載階段(解析階段)或者第一次使用的時候就轉化爲直接引用,這種轉化成爲靜態解析,另一部分在沒一次運行期間轉化爲直接引用,這部分成爲動態連接。

4、方法返回地址

一個方法在執行時,只有兩種方式退出這個方法:正常完成出口和異常完成出口。

  • 正常完成出口:執行引擎遇到一個方法返回的字節碼指令,這時候執行引擎讀取棧幀中的方法返回地址,將返回值傳遞給上層的方法調用者。
  • 異常完成出口:在方法執行過程中遇到了異常,並且這個異常沒有在方法體內得到處理,也就是在本地異常表內沒有搜索到匹配的異常處理器,就會導致方法退出。這時候執行引擎不會讀取方法返回地址而直接停止執行,上層調用者不會得到任何返回值。

方法調用過程:
方法退出的過程實際上等同於把當前棧幀出棧。恢復上層方法的局部變量表和操作數棧,把返回值壓入調用者棧幀的操作數棧中,調整PC計數器的值以執行方法調用指令後面的一條指令。

一般把動態連接、方法返回地址和其他附加信息全部歸爲一類,成爲棧幀信息。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章