14 執行時棧幀結構
阿新 • • 發佈:2019-01-23
《深入理解Java虛擬機器:JVM高階特性與最佳實踐(第2版)》8.2節
不同的虛擬機器實現在執行Java程式碼時可能會有解釋執行(通過直譯器執行)和編譯執行(通過即時編譯器產生原生代碼執行)兩種選擇
一組變數值儲存空間,存放方法引數和方法內部定義的區域性變數
容量以變數槽(Variable Slot,下稱Slot)為最小單位,Class檔案中Code屬性的max_locals資料項確定該表最大容量
每個Slot能存放一個boolean、byte、char、short、int、float、reference或returnAddress型別資料
64位的long和double型別資料,以高位對齊方式佔2個連續Slot,區域性變量表建立線上程的堆疊上,是執行緒私有資料,無論讀寫兩個連續Slot是否為原子操作,都不會引起資料安全問題
虛擬機器通過索引定位方式使用區域性變量表,索引值範圍從0至最大Slot數量
方法執行時,虛擬機器使用區域性變量表完成引數值到引數變數列表的傳遞過程
若執行例項方法(非static方法),則區域性變量表中0位索引Slot預設傳遞方法所屬物件例項引用,即"this",其餘引數按引數表順序從1開始排列,引數表分配完畢後,根據方法體內定義變數順序和作用域分配其餘Slot
為節省棧幀空間Slot可重用,方法體中定義的區域性變數作用域不一定覆蓋整個方法體,若當前位元組碼PC計數器的值已超出某變數作用域,則該變數對應Slot可交給其他變數使用,但這樣的設計會伴隨一些副作用
定義了局部變數但是未賦值是不能使用的
也稱操作棧,是一個後入先出(Last In First Out, LIFO)棧
Class檔案中Code屬性的max_stacks資料項確定該棧最大深度
32位資料型別佔棧容量為1,64位資料型別佔棧容量為2
概念模型中兩個棧幀完全獨立,但大多虛擬機器實現會做優化處理,使兩個棧幀出現部分重疊,這樣,在進行方法呼叫時可共用一部分資料,無須額外引數複製傳遞
Java虛擬機器解釋執行引擎稱為“基於棧的執行引擎”,其中的“棧”就是運算元棧
方法開始執行後有兩種退出方式:
1) 正常完成出口(Normal Method Invocation Completion),執行引擎遇到方法返回指令,方法返回指令決定是否有返回值傳遞給上層方法呼叫者
2) 異常完成出口(Abrupt Method Invocation Completion),方法執行過程中遇到異常,且該異常未在方法體內處理,無論是Java虛擬機器內部的異常,還是athrow指令產生的異常,只要在該方法異常表中未搜尋到匹配異常處理器,就會導致方法退出,這時不會有返回值傳遞給上層方法呼叫者
無論以何種方式退出,都需返回到方法被呼叫位置,程式才能繼續執行,方法返回時可能需要在棧幀中儲存一些資訊,用來幫助恢復上層方法的執行狀態:
1) 方法正常退出時,呼叫者PC計數器的值可作為返回地址,棧幀中可能會儲存這個計數器值
2) 方法異常退出時,返回地址由異常處理器表決定,棧幀中一般不會儲存這部分資訊
方法退出過程實際上等同於當前棧幀出棧,故退出時可能執行的操作有:
1) 恢復上層方法區域性變量表和運算元棧
2) 把返回值(如果有)壓入呼叫者棧幀運算元棧
3) 調整PC計數器的值以指向方法呼叫指令後面一條指令
棧幀(Stack Frame)
用於支援虛擬機器進行方法呼叫和方法執行的資料結構,是虛擬機器棧(Virtual Machine Stack)的棧元素 儲存方法的區域性變量表、運算元棧、動態連線和方法返回地址等資訊 每個方法從呼叫開始至執行完成,對應一個棧幀從入棧到出棧 編譯程式程式碼時,棧幀大小已完全確定,故一個棧幀需分配多少記憶體,不受程式執行期變數資料影響,僅取決於具體虛擬機器實現 對於執行引擎,在活動執行緒中只有棧頂棧幀有效,稱當前棧幀(Current Stack Frame),位元組碼指令只操作當前棧幀 與當前棧幀關聯的方法稱當前方法(Current Method)1. 區域性變量表(Local Variable Table)
2. 運算元棧(Operand Stack)
Java虛擬機器解釋執行引擎稱為“基於棧的執行引擎”,其中的“棧”就是運算元棧