Java虛擬機已方法作為最基本的執行單位。
棧幀:是支持Java虛擬機進行方法調用和方法執行背后的數據結構。
棧幀存儲了方法的 局部變量表、操作數棧、動態連接和放回地址等信息。
每一個方法的調用開始和執行結束,都對應著一個棧幀在虛擬機棧里面從入棧到出棧的過程。
棧幀內存
一個棧楨需要分配多少內存,并不會受程序運行期變量數據的影響,而僅僅取決于程序源碼和具體的虛擬機實現的棧內存布局形式。
棧幀運行
對于執行引擎來講,在活動線程中,只有位于棧頂的方法才是運行的,只有位于棧頂的棧幀才是生效的,其被稱為“當前棧幀”,與這個棧幀所關聯的方法稱為“當前方法”。
1. 局部變量表
局部變量表是一組變量值的存儲空間,用于存放方法參數和方法內部定義的局部變量
線程安全
由于局部變量表是建立在線程堆棧中的,屬于線程私有的數據,無論讀寫兩個連續的變量槽是否為原子操作,都不會引起數據競爭和線程安全問題。
????????當一個方法被調用時,Java虛擬機會使用局部變量表來完成參數值到參數變量列表的傳遞過程,即實參到形參的傳遞。如果執行的是實例方法(沒有被static修飾的方法),那局部變量表中第0位索引的變量槽默認是用于傳遞方法所屬對象實例的引用,在方法中可以通過關鍵字“this”來訪問到這個隱含的參數。其余參數則按照參數表順序排列,占用從1開始的局部變量槽,參數表分配完畢后,再根據方法體內部定義的變量順序和作用域分配其余的變量槽。
2. 操作數棧
操作數棧也常被稱為操作棧,它是一個后入先出棧。
功能:
當一個方法剛剛開始執行的時候,這個方法的操作數棧是空的,在方法的執行過程中,會有各種字節碼指令往操作數棧中寫入和提取內容,也就是出棧和入棧操作。
????????當一個方法剛剛開始執行的時候,這個方法的操作數棧是空的,在方法的執行過程中,會有各種字節碼指令往操作數棧中寫入和提取內容,也就是出棧和入棧操作。如在做算術運算的時候是通過將運算涉及的操作數棧壓入棧頂后調用運算指令來進行的,又如在調用其他方法的時候是通過操作數棧來進行方法參數的傳遞。舉個例子,例如整數加法的字節碼指令iadd,這條指令在運行的時候要求操作數棧中最接近棧頂的兩個元素已經存入了兩個int型的數值,當執行這個指令時,會把這兩個int值出棧并相加,然后將相加的結果重新入棧。
數據共享:
兩個不同的棧幀作為不同方法的虛擬機棧元素,是完全相互獨立的。但虛擬機的實現里都會進一步優化處理,令兩個棧楨重疊,可以節約一部分空間,并且共用一部分數據。
3. 動態連接
????????每個棧幀都包含一個指向運行時常量池中該棧幀所述方法的引用,持有這個引用是為了支持方法調用過程中的動態連接。
????????字節碼中的方法調用指令就以常量池里指向方法的符號引用作為參數。這些符號引用一部分會在類加載階段或者第一次使用的時候就被轉化為直接引用,這種轉化被稱為靜態解析。
????????另外一部分將在每一次運行期間都轉化為直接引用,這部分就稱為動態連接。
4. 方法返回地址
當一個方法返回后,只有兩種方式退出這個方法。
-
執行引擎遇到任意一個方法返回的字節碼指令。
-
方法執行的過程中遇到了異常。
無論采用何種退出方式,在方法退出之后,都必須返回到最初方法被調用的位置????????
????????方法退出的過程實際上等同于把當前棧幀出棧,因此退出時可能執行的操作有:恢復上層方法的局部變量表和操作數棧,把返回值(如果有的話)壓入調用者棧幀的操作數棧中,調整PC計數器的值以指向方法調用指令后面的一條指令等。筆者這里寫的“可能”是由于這是基于概念模型的討論,只有具體到某一款Java虛 擬機實現,會執行哪些操作才能確定下來。
5. 附加信息
《Java虛擬機規范》允許虛擬機實現增加一些規范里沒有描述的信息到棧幀之中,例如與調試、性能收集相關的信息。