棧幀的內部結構:
局部變量表(Local Variables)
操作數棧(Operand Stack)
動態鏈接(Dynamic Linking)
方法返回地址(Return Address)
一些附加信息
1.局部變量表
局部變量表:也被稱作本地變量表或局部變量數組
定義為一個數字數組,主要用於存儲方法參數和定義在方法體內的局部變量
這些數據類型包括基本數據類型,對象引用(reference),以及returnAddress類型
由於局部變量表是基於線程的棧上,是線程的私有數據,因此不存在數據安全問題
局部變量表所需容量的的大小是在編譯期確定下來的,並保存在方法Code屬性的maximum local variables數據項中。在方法運行期間是不會改變局部變量的大小的
方法嵌套的次數由棧的大小確定,一般來說,棧越大,方法嵌套調用次數越多。對一個函數而言,它的參數和局部變量越多,使得局部變量表膨脹,它的棧幀就越大,以滿足方法調用所需傳遞的信息增大的需求。進而函數調用就會占用更多的棧空間,導致其嵌套調用次數就會減少
局部變量表中的變量自在當前方法調用中有效。在方法執行時,虛擬機通過使用局部變量表完成參數值到參數變量列表的傳遞過程。當方法調用結束后,隨着方法棧幀的銷毀,局部變量表也會隨之銷毀。
字節碼指令的行號和程序代碼的行號對應表:
上邊是LineNumberTable
下邊是LocalVariableTable(局部變量表) 起始位置(Start PC) 長度(Length) 索引(Index) 變量名(Name) 變量類型(就是Name后面的那個東東)
強調一下:Length+Start PC就是字節碼指令的總長度【Code Length】,Length和Start PC反映的是變量的有效范圍
以上的圖都是靜態方法的,沒有this
關於Solt的理解
solt是局部變量表的基本單元,也叫槽
參數值存放總是在局部數組的index0開始,到數組長度-1的索引結束。
局部變量表(數組)最基本的存儲單元是Solt
局部變量表存放編譯期可知的各種數據類型(8種),引用類型(reference),returnAddress類型的變量。
在局部變量表里,32位以內的類型之占一個slot(包括returnAddress類型),64位的類型(long(8個字節8*8=64位)和double(8Bytes*8=64位))占用兩個solt。
➢byte、short 、char 在存儲前被轉換為int,boolean 也被轉換為int,0表示false,非0表示true。
➢long和double則占據兩個Slot。
JVM會為局部變量表中的每一個Slot都分配一個訪問索引,通過這個索引即可成功訪問到局部變量表中的局部變量值
當一個實例方法被調用的時候,它的方法參數和方法內部定義的局部變量將會按照順序被復制到局部變量表的每一個slot上【大概意思就是先聲明誰,先分配】
如果需要訪問局部變量表中一個64bit局部變量時,只需要使用起始索引
如果當前幀是由構造方法或者實例方法創建的(非靜態方法,靜態方法沒有this),那么該對象引用的this會存放在index為0的slot處,其余參數按順序繼續排順序
Slot可以重復利用:
b變量出了括號就沒了,所以c變量用了b回收的槽
非靜態方法實例:
靜態變量與局部變量的對比:https://www.cnblogs.com/Timeouting-Study/p/12502750.html
局部變量表補充說明:
在棧幀中,與性能調優關系最密切的就是前邊提到的局部變量表。在方法執行時,虛擬機使用局部變量表完成方法的傳遞。
局部變量表中的變量也是重要的垃圾回收根節點,只要被局部變量表安中直接或間接引用的對象都不會被垃圾回收