Java虛擬機棧

Java Virtual Machine Stacksjvm

  • 線程私有,生命週期與線程相同,描述的是Java方法執行的內存模型。函數

  • 每個方法執行的同時都會建立一個棧幀(Stack Frame),用於存儲局部變量表、操做數棧、動態連接、方法出口等信息。每個方法的執行就對應着棧幀在虛擬機棧中的入棧,出棧過程。spa

一、局部變量表:線程

  • 存放編譯期可知的各類基本數據類型、對象引用類型和returnAddress類型(指向一條字節碼指令的地址:函數返回地址)。對象

  • long、double佔用兩個局部變量空間Slot。生命週期

  • 局部變量表所需的內存空間在編譯期肯定,當進入一個方法時,方法在棧幀中所須要分配的局部變量空間是徹底肯定的,不可動態改變大小。內存

  • 異常:線程請求的棧幀深度大於虛擬機所容許的深度---StackOverFlowError,若是虛擬機棧能夠動態擴展(大部分虛擬機容許動態擴展,也能夠設置固定大小的虛擬機棧),可是沒法申請到足夠的內存---OutOfMemorError。虛擬機

二、操做數棧:編譯

  • 後進先出LIFO,最大深度由編譯期肯定。棧幀剛創建時,操做數棧爲空,執行方法操做時,操做數棧用於存放JVM從局部變量表複製的常量或者變量,提供提取,及結果入棧,也用於存放調用方法須要的參數及接受方法返回的結果。變量

  • 操做數棧能夠存放一個jvm中定義的任意數據類型的值。

  • 在任意時刻,操做數棧都一個固定的棧深度,基本類型除了long、double佔用兩個深度,其它佔用一個深度。

三、動態鏈接:

  • 每一個棧幀都包含一個指向運行時常量池中該棧幀所屬方法的引用,持有這個引用是爲了支持方法調用過程當中的動態鏈接。

  • Class文件的常量池中存在有大量的符號引用,字節碼中的方法調用指令就以常量池中指向方法的符號引用爲參數。這些符號引用,一部分會在類加載階段或第一次使用的時候轉化爲直接引用(如final、static域等),稱爲靜態解析,另外一部分將在每一次的運行期間轉化爲直接引用,這部分稱爲動態鏈接。

四、方法返回地址:

  • 當一個方法被執行後,有兩種方式退出該方法:執行引擎遇到了任意一個方法返回的字節碼指令或遇到了異常,而且該異常沒有在方法體內獲得處理。不管採用何種退出方式,在方法退出以後,都須要返回到方法被調用的位置,程序才能繼續執行。方法返回時可能須要在棧幀中保存一些信息,用來幫助恢復它的上層方法的執行狀態。通常來講,方法正常退出時,調用者的PC計數器的值就能夠做爲返回地址,棧幀中極可能保存了這個計數器值,而方法異常退出時,返回地址是要經過異常處理器來肯定的,棧幀中通常不會保存這部分信息。

  • 方法退出的過程實際上等同於把當前棧幀出棧,所以退出時可能執行的操做有:恢復上層方法的局部變量表和操做數棧,若是有返回值,則把它壓入調用者棧幀的操做數棧中,調整PC計數器的值以指向方法調用指令後面的一條指令。

相關文章
相關標籤/搜索