棧幀是虛擬機運行時數據區中的虛擬機棧的棧元素,棧幀存儲了方法的局部變量表,操做數棧,動態鏈接,方法返回地址,在編譯程序代碼的時候,棧幀中須要多大的局部變量表、多深的操做數棧都已經徹底肯定了,而且寫入到方法表的Code屬性之中。
java
其最大容量由方法的Code屬性,max_locals肯定,局部變量表的容量以變量槽(Slot)爲最小單位,Long和Double佔用兩個空間,其讀寫是非原子性的,其會佔用n與n+1兩個Slot,不容許採用任何方式單獨訪問其中的一個Slot。性能
在方法執行時,虛擬機是使用局部變量表來完成參數值到變量表的傳遞,若是執行的是實例方法,那麼局部變量表第0位索引的Slot默認是用於傳遞方法所屬的對象實例的引用,其他參數從索引1開始佔用Slot,參數表分配完畢後,再根據方法體內部定義的變量順序和做用域分配其他的Slot,爲了儘量的節省棧幀空間,局部變量表中的Solt是能夠重用的,當PC計數器的值,已經超出方法體中定義的變量的做用域時,其佔用的Slot會被其餘做用域的變量重用。對象
其最大深度由方法的Code屬性的max_stacks決定,有些虛擬機實現上,會讓相鄰的兩個棧幀出現一些 共享部分,方便方法調用之間共享數據。blog
每一個棧幀都包含一個指向運行時常量池中該幀所屬方法的引用,這個引用是爲了支持方法調用過程當中的動態鏈接。繼承
當一個方法執行之後,只有兩種方式能夠退出這個方法,一個是執行引擎遇到一個返回的字節碼指令,這時候可能會有返回值傳遞給上層的方法調用者,這種退出方法被稱爲正常完成出口,另外一種退出方式是,在方法的執行過程當中遇到了異常,只要在本方法的異常表中沒有搜索到匹配的異常處理器,就會致使方法退出,這種退出方式被稱爲異常完成出口,這種方式是不會給它的上層調用者返回任何返回值的。索引
不管任何方式退出,都須要返回到方法被調用的位置,程序才能繼續執行,因此方法退出時會恢復上層方法的局部變量表和操做數棧,把返回值壓入調用者的操做數棧,調整PC至下一條指令地址。ip
方法調用階段惟一的任務就是肯定被調用方法的版本作用域
方法的調用包括解析與分派兩種方式虛擬機
動態分派的解析過程(invokevirtual指令爲例):編譯
出於性能的考慮,會爲類在方法區創建一個虛方法表,使用虛方法表索引來代替元數據查找以提升性能
本文參考:《深刻理解Java虛擬機》