JVM棧是由棧幀組成的,一個方法對應一個棧幀,方法執行完後彈棧。數據結構
運行時棧幀結構:棧幀是JVM棧(Stack)中的基本單元,是方法調用和執行的數據結構。對象
每個棧幀(Frame)內部存儲有方法的局部變量表(LocalVariables)、操做數棧(OperandStack)、動態鏈接(CurrentClassConstantPoolReference)、方法返回地址(ReturnValue)和一些額外的附加信息。這些數據在class文件中已肯定,因此每一個棧幀的內存大小不受運行期數據變化的影響。接口
局部變量表(LocalVariables)圖片
局部變量表存放方法中用到的8中基本數據類型的值以及對象的引用。對象的引用有兩個功能:1,在堆中能找到實際的對象;2,在方法去的中能找到該對象的類型信息。 注意:局部變量必須顯式的賦初始值,虛擬機不會對局部變量賦默認值。編譯器能夠檢測這點錯誤。內存
操做數棧(OperandStack)編譯器
存放字節碼指令。後入先出。剛開始執行方法時棧內元素爲空。操做數棧的大小在class文件中已肯定。虛擬機
動態鏈接(CurrentClassConstantPoolReference) 編譯後的class文件只有符號引用。運行期才能獲取實際的引用或句柄。it
方法返回地址(ReturnValue)編譯
方法結束的兩種方式:1,return;2,異常。 被調用的棧幀的方法返回地址記錄了調用的棧幀的執行地址,方便在前者執行完彈棧後PC寄存器能夠繼續執行後者的代碼class
附加信息 虛擬機規範容許具體的虛擬機實現增長一些規範裏沒有描述的信息到棧幀之中。
方法調用:
方法調用應不等於方法執行,方法調用階段惟一的任務就是肯定調用哪一個方法,不涉及方法的具體執行。 好比,調用某個接口實現類的某個接口方法,須要在運行期找到接口的具體實現類的這個方法的具體實現。(動態分派)
解析調用是一個靜態過程,在編譯期間就已徹底肯定,類加載階段肯定靜態方法和私有方法的符號引用轉直接引用,在調用時肯定其餘方法的符號引用轉直接引用。
靜態分派: 全部依賴靜態類型來定位方法執行版本的分派動做成爲靜態分派,典型應用好比參數類型爲子類和父類的方法重載。 Father f = new Son(). 有兩個重載方法 test(Father father) test(Son son),在執行test(f)的時候,編譯器就已知是調用的前者,這種定位稱爲靜態分派。
動態分派: Father f = new Son() Father有個方法test(),Son重寫了這個test()方法,這調用f.test()的時候定位到後者,這種定位稱爲動態分派。
單分派和多分派: 同時根據調用者的對象類型和方法參數來定位方法。
方法執行: 在OperatedStatck中執行方法方法調用階段定位的區MethodCode中的指令集
附上網上找的一張圖,經典:
參考資料: