編譯期就確定了需要多大的區域性變數表,多深的運算元棧,這些資訊全在位元組碼中。
只有位於棧頂的棧幀才有效,稱為當前棧幀,所對應的方法就是當前正在執行的方法。
容量以變數槽slot為單位,slot記憶體大小隨著需求而變化並且不固定。
方法執行時jvm使用區域性變數表完成引數值到引數列表的傳遞過程。
slot可以被其他變數復用。
區域性變數不存在準備階段,所以不會賦予系統初始值,如果不初始化那麼他就不能使用。
jvm通過索引定位的方式定位slot,從0到最大slot數量。0位索引slot是用來存放方法所屬物件例項的引用(this),之後按引數列表分配slot,再後按照區域性變數順序分配slot。
類載入的解析階段會把 部分符號引用轉化為直接引用,但這種解析的前提條件就是:方法在程式執行之前就有乙個就可以確定的版本,並且在執行期間不可變。
編譯期可知執行期不可變這種方法有static和private方法,想想也是,這兩種方法只有定義他們的類才能呼叫,他們一出生就確定了唯一的主人。他們不可能被繼承或者重寫其他版本。
例項構造器,父類方法這2中也能確定唯一的版本,所以這些方法也是在類載入階段解析為直接引用。
靜態方法,私有方法,例項構造器,父類方法這些方法可確定唯一版本所以統稱為 非虛方法,final方法也是非虛方法。
靜態型別和動態型別
靜態分派:根據引數的靜態型別確定該方法使用的版本
動態分派:執行期間根據呼叫方法的物件的實際型別確定使用哪個類的方法,也就是確定使用哪個重寫方法。編譯期間無法確定實際型別找到呼叫當前方法的物件的實際型別
在實際型別中由靜態分派確定方法版本。
如果找到對應版本則檢查訪問許可權如果通過則返回此方法的引用。
如果找不到則從下往上在父類中找,如果找不到則丟擲異常。
單分派多分派
靜態分派和動態分派的區別靜態分派通過引數型別查詢過載版本,並且是引數的靜態型別。
動態分派通過呼叫方法的物件查詢重寫版本,並且是物件的實際型別。
當乙個引用變數它的編譯時的型別和執行是的型別不一樣時:
jvm 位元組碼執行流程
1 源 public class mytest 2 編譯後的位元組碼檔案 3 載入 1 常量池中的位元組碼載入到執行時常量池 2 方法的位元組碼載入到方法區 4 main執行緒開始執行,分配棧楨記憶體 1 棧記憶體的分配 區域性變數表 4 最大運算元棧的深度為 2 2 執行istore 1指令 將常...
JVM之虛擬機器位元組碼執行引擎
執行時棧幀結構 棧幀儲存方法的區域性變數表 運算元棧 動態鏈結和方法返回位址等,每乙個方法由開始到結束,都對應著乙個棧幀在虛擬機器裡面的出棧入棧過程。對於執行引擎來說,在活動的執行緒中,只有位於棧頂的棧幀才有效,叫做當前棧幀,與這個棧幀相關聯的方法叫做當前方法。區域性變數表 是一組變數值儲存空間,存...
一夜搞懂 JVM 位元組碼執行引擎
我的 github 部落格 編譯的結果從本地機器碼轉變為位元組碼,是儲存格式發展的一小步,卻是程式語言發展的一大步 首先,丟擲靈魂三問 如果你對上述問題理解得還不是特別透徹的話,可以看下這篇文章 如果理解了,你可以關閉網頁,開啟遊戲放鬆了hhh 下面,筆者將帶你 jvm核心的組成部分之一 執行引擎。...