java虛擬機規范-運行時棧幀


前言

java虛擬機是java跨平台的基石,本文的描述以jdk7.0為准,其他版本可能會有一些微調。

引用

棧幀

  • 每當一個java方法被執行時都會在虛擬機中新創建一個棧幀,方法調用結束后即被銷毀。
  • 棧幀存儲空間為虛擬機棧,每一個棧幀都有自己的局部變量表、操作數棧和指向當前方法所屬的類的運行時常量池的引用。
  • 在每個線程中,只有目前正在執行的那個方法的棧幀是活動的。這個棧幀就稱為當前棧幀(current frame),這個棧幀對應的方法稱之為當前方法(current method)。定義這個方法的類就稱之為當前類(current class)。對局部變量表和操作數棧的各種操作,通常都指的是對當前棧幀的局部變量表和操作數棧進行的操作。如下圖所示,

變量

局部變量

  • 每一個棧幀包含一組局部變量,這組局部變量中包含了方法運行時所需要的所有的變量(含this引用)、方法參數和其他定義的局部變量。局部變量的類型包括以下幾種:
    • boolean
    • byte
    • char
    • short
    • int
    • float
    • reference
    • returnAddress
    • long
    • double
  • 除了long和double外,其他所有的變量在局部變量表中都只占一個槽位(slot),而long和double占2個槽位。
  • 特別值得一提的是,當一個實例方法被調用的時候,局部變量表中的第0個局部變量一定是用來存儲被調用的實例方法所在的對象引用。(this關鍵字,可以參考下面示例中的字節碼截圖),后續的其他參數將會傳遞至從1開始的局部變量表位置上。
  • 示例:
    • 以下圖中的代碼為例:
    • 對應的字節碼如下:
    • 具體的操作流程示意:
  • 釋義:
    • 從上圖中我們可以看出例如int x=12,在jvm中對應着兩個指令
      • bipush 10,bipush指令用於將一個byte作為一個整型數字插入到操作數棧中(oprand stack),這里將10插入到操作數棧
      • istore_1,istore_1指令(實際上這個應該稱之為操作碼opcode,指令是指操作碼加上操作數oprand)是istore_ 指令組中的一個,用於將一個整型數字存儲到局部變量中, <n>代表的是局部變量表中的存儲位置,同時只能為0,1,2,3;超過3了就只能使用istore指令。
    • 注意,istore_1操作碼和istore 4指令兩者的區別為
      • 前者只是一個操作碼,只占一個單位的長度,后者是操作碼和操作數組合的指令,占2個單位的長度。(注意看Code中每一行指令前面的數字)
  • 思考:
    • 看了上圖的字節碼中可能有人會問,為什么還需要istore和iload這兩個指令呢?這是因為棧本身不是用來存儲數據的,而是用局部變量表來存儲。局部變量通過索引尋址。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM