關於Java虛擬機棧局部變最表slot的理解

局部變最表是一組變量值存儲空間,用於存放方法參數和方法內部定義的局部變量。在 Java程序被編譯爲 Class文件時,就在方法的 Code屬性的max_locals數據項中確定了該方法所需要分配的最大局部變量表的容量。

局部變量表的容量以變量槽(variable slot,下稱slot)爲最小單位,虛擬機規範中並沒有明確指明一個slot應占用的內存空間大小,只是很有“導向性”地說明每個slot都應該能存放一個boolean、byte、char、short、int、float、reference或returnAddress類型的數據,這種描述與明確指出“每個slot佔用32位長度的內存空間”有一些差別,它允許slot的長度隨着處理器、操作系統或虛擬機的不同而發生變化。不過無論如何,即使在64位虛擬機中使用了64位長度的內存空間來實現一個slot,虛擬機仍要使用對齊和補白的手段讓slot在外觀上看起來與32位虛擬機中的一致。

既然前面提到了數據類型,在此順便說一下,一個slot可以存放一個32位以內的數據類型,Java中佔用32位以內的數據類型有boolean、byte、char、short、int、float、refcrcnce和retumAddress八種類型.前面六種不需要多加解釋,大家都認識,而後面的referencc是對象的引用。虛擬機規範既沒有說明它的長度,也沒有明確指出這個引用應有怎樣的結構,但是一般來說,虛擬機實現至少都應當能從此引用中直接或間接地查找到對象在Java堆中的起始地址索引和方法區中的對象類型數據。而:etumAddress是爲字節碼指令jsr、jsr_w和ret服務的,它指向了一條字節碼指令的地址。

對於64位的數據類型,虛擬機會以高位在前的方式爲其分配兩個連續的slot空間。Java語言中明確規定的64位的數據類型只有long和double兩種(reference類型則可能是32位也可能是64位)。值得一提的是,這裏把long和double數據類型分割存儲的做法與“long和double的非原子性協定”中把一次long和double數據類型讀寫分割爲兩次32位讀寫的做法類似,讀者閱讀到Java內存模型時可以對比一下。不過,由於局部變量表建立在線程的堆棧上,是線程私有的數據,無論讀寫兩個連續的 slot 是否是原子操作,都不會引起數據安全問題。

虛擬機通過索引定位的方式使用局部變量表,索引值的範圍是從0開始到局部變量表最大的slot數量。如果是32位數據類型的變量,索引n就代表了使用第n個slot, 如果是64位數據類型的變量,則說明要使用第n和第n+l兩個slot。在方法執行時,虛擬機是使用局部變量表完成參數值到參數變量列表的傳遞過程的,如果是實例方法(非 static的方法),那麼局部變量表中第0位索引的slot默認是用於傳遞方法所屬對象實例的引用,在方法中可以通過關鍵字“this”來訪問這個隱含的參數。其餘參數則按照參數表的順序來排列,佔用從1開始的局部變量slot,參數表分配完畢後,再根據方法體內部定義的變量順序和作用域分配其餘的slot。
局部變量表中的slot是可重用的,方法體中定義的變量,其作用域並不一定會覆蓋整個方法體,如果當前字節碼PC計數器的值已經超出了某個變量的作用域,那麼這個變量對應的slot就可以交給其他變量使用。這樣的設計不僅僅是爲了節省棧空間,在某些情況下slot的複用會直接影響到系統的垃圾收集行爲。
局部變量不像成員變量在定義的時候賦初始值。
變量槽slot的理解與演示

  1. 參數值的存放總是在局部變量數組的index0開始,到數組長度-1的索引結束
  2. 局部變量表,最基本的存儲單元是Slot(變量槽)
  3. 局部變量表中存放編譯期可知的各種基本數據類型(8種),引用類型(reference),returnAddress類型的變量。
  4. 在局部變量表裏,32位以內的類型只佔用一個slot(包括returnAddress類型),64位的類型(long和double)佔用兩個slot。byte、short、char、float在存儲前被轉換爲int,boolean也被轉換爲int,0表示false,非0表示true;long和double則佔據兩個slot。
  5. JVM會爲局部變量表中的每一個slot都分配一個訪問索引,通過這個索引即可成功訪問到局部變量表中指定的局部變量值
  6. 當一個實例方法被調用的時候,它的方法參數和方法體內部定義的局部變量將會按照聲明順序被複制到局部變量表中的每一個slot上
  7. 如果需要訪問局部變量表中一個64bit的局部變量值時,只需要使用前一個索引即可。(比如:訪問long或者double類型變量)
  8. 如果當前幀是由構造方法或者實例方法創建的(意思是當前幀所對應的方法是構造器方法或者是普通的實例方法),那麼該對象引用this將會存放在index爲0的slot處,其餘的參數按照參數表順序排列。
  9. 靜態方法中不能引用this,是因爲靜態方法所對應的棧幀當中的局部變量表中不存在this
  10. slot的數量保持不變
    在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述
由以上可以看出,slot的數量保持不變,b變量出了它的作用域之後就沒有了,c變量佔用b的Slot

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章