個人全部文章同步更新與Github--Java-Notes,想了解JVM,HashMap源碼分析,spring相關,劍指offer題解(Java版),能夠點個star。能夠看個人github主頁,天天都在更新喲。java
邀請您跟我一同完成 repogit
棧幀是虛擬機棧的一個單位,以前講解了運行時數據區和類加載的過程,如今咱們看下虛擬機中棧幀都是啥樣子的,這個應該算是運行時數據區(JVM內存結構的補充),若是不瞭解能夠參考個人這篇博文 JVM內存結構github
運行時棧幀中存儲瞭如下內容spring
每個方法的調用開始和結束都是棧的壓入(入棧)和彈出(出棧)的過程數組
局部變量表是一組變量值存儲空間,用於存放方法參數和方法內部定義的局部變量。工具
大小是編譯的時候寫進了字節碼裏面的,在Code屬性中的max_local屬性,即下面的local源碼分析
局部變量表的容量以變量槽(Variable Slot)爲最小單位,虛擬機中並無明確指明一個Slot應占用的內存空間大小,只是頗有導向性的說到每一個Slot都應該能存放一個下面8種類型的其中一個。(若是是long或者double這種64位的數據類型,則須要兩個Slot)spa
前六種應該不用說,是基本的數據類型,reference是啥呢code
reference是一個對象實例的引用cdn
做用:
爲字節碼指令jsr、jsr_w和ret提供的,指向了一條字節碼指令的地址
已經不多見了。
局部變量表中的局部變量和以前將類加載的時候的類變量(static修飾)不同,他沒有所謂的"準備階段",因此沒有設置初始值的階段。不知道的能夠參考我類加載這篇文章,看了準備階段,應該就知道了。類加載過程
因此咱們在寫程序的時候這樣寫,對比你就知道了
其餘類型零值
不使用的對象,應當手動賦值爲null
爲了儘量節省棧空間,局部變量表的Slot能夠複用。方法體中定義的變量,其做用域並不必定覆蓋整個方法體,若是當前字節碼PC計數器的值已經超出了某個變量的做用域,那這個變量對應的Slot就能夠交給其餘變量使用。
不過這樣的作法,會有一些缺點,咱們來看下面的代碼示例
public class Test2 {
public static void main(String[] args) {
byte[] placeholder = new byte[64 * 1024 * 1024];
System.gc();
}
}
複製代碼
咱們經過配置虛擬機參數-verbose:gc
來打印垃圾回收的結果
咱們看到他並無回收。
咱們修改一下代碼
public class Test2 {
public static void main(String[] args) {
{
byte[] placeholder = new byte[64 * 1024 * 1024];
}
System.gc();
}
}
複製代碼
他仍是沒有進行回收,按理說 placeHolder 的做用域只在花括號中,在執行gc方法的時候,他就已經不可能用了,算是已經"死"了的對象了,爲何沒有回收呢?
咱們再修改一下
public class Test2 {
public static void main(String[] args) {
{
byte[] placeholder = new byte[64 * 1024 * 1024];
}
int a = 0;
System.gc();
}
}
複製代碼
咱們看到,此次垃圾回收器工做了,爲何呢?
placeholder 可否被回收的根本緣由是:局部變量表的Slot是否還存有關於placeholder數組對象的引用。
第一次修改中,代碼雖然離開了該變量的做用域,可是在此以後,沒有任何對局部變量表的讀寫操做,該變量本來佔用的Slot尚未被任何其餘變量複用,因此做爲GC Root 一部分的局部變量表仍然保持着對他的關聯(不瞭解什麼能夠做爲GC Root的話,能夠參考個人這篇文章 JVM垃圾回收)
而第二次,則改變了上面的這種狀況
因此當遇到一個方法,其後面的代碼有一些耗時很長的操做,而前面又定義了佔用大量內存、實際上已經用不到的變量,應當手動設置其爲null。
不少工具類都有這個操做,好比 ArrayList和Stack中的remove方法,你也能夠找下其餘的工具類中的方法,看是否有此類操做
操做數棧記錄了一個方法執行過程當中的字節碼指令,他往操做數棧中進行入棧和出棧
大小在編譯的時候也已經肯定了,字節碼文件中的Code屬性中的max_stacks數據項,即下圖的stack
當一個方法剛執行的時候,操做數棧是空的,在方法執行的過程當中,會有各類字節碼指令往操做數棧中入棧和出棧。
每個棧幀都包含一個指向運行時常量池中該棧幀所屬的方法的引用,持有這個引用是爲了支持方法調用過程當中的動態鏈接
若是你看了字節碼文件構成和類加載過程,你應該知道,字節碼文件中有不少符號引用。
這些符號引用一部分會在類加載的解析階段或者第一次使用的時候轉化爲直接引用,這種轉化稱爲靜態解析
另外一部分會在運行期間轉化爲直接引用,這部分稱爲動態鏈接
動態鏈接會在這篇文章 方法調用 中講解
一個方法執行後,只有兩種方法能夠退出:
方法退出時可能的操做:
這部分信息徹底取決於具體的虛擬機實現,有的可能有,有的沒有。