更新時間:2020-10-09 17:30:54 來源:動力節點 瀏覽1486次
JVM棧,全稱為Java 虛擬機棧,線程私有,生命周期和線程一致。描述的是 Java 方法執行的內存模型:每個方法在執行時都會床創建一個棧幀(Stack Frame)用于存儲局部變量表、操作數棧、動態鏈接、方法出口等信息。每一個方法從調用直至執行結束,就對應著一個棧幀從虛擬機棧中入棧到出棧的過程。
當程序開始執行時,由于只有一個main線程,因而JVM只需要為main線程分配好棧區的內存(話句話說如果有多個線程,自然就會有多個棧區,并且為各自線程私有)。main繼續執行,就會遇到main()方法,遇到之后呢!JVM又會在棧區當中再劃出一個小塊來存放main()方法執行過程的數據,這一小塊區域也就是棧幀。main()方法執行過程中又有一個add()方法出現了,同樣地,JVM又會再為add()分配一個棧幀,同時壓入到棧區,以后再遇到其他方法也是如此。當然,方法在執行完成之后,便會彈出并釋放內存,當線程中棧區的所有方法都返回之后,程序也就算是執行完畢了。
當我們扯開棧區,撕開棧幀,一不小心,局部變量表、操作數棧、動態鏈接、方法出口......嘩啦啦地散落一地。
撿起add()棧幀的局部變量表和操作數棧就可以看到這樣一個畫面,在執行例子中add()方法中的三行代碼時,局部變量表和操作數棧的一個變化過程:首先,執行int a = 3;局部變量表中會分配出一個int區域,表示為a;同時iconst命令使得操作數棧中壓入了常量3,然后再由istore命令將3彈出,賦值給局部變量表中a。同樣,int b = 4; 這一行代碼也是如此。然后,int c = a + b;從右往左開始,先執行a + b,也就是iload命令從局部變量中取出a、b對應的值,再將iadd后的值push進操作數棧中,剩下的便是int c = 7的操作了。
通過上面的例子,就很容易明白;局部變量表,顧名思義就是存放每個方法中的局部變量(即編譯器可知的各種基本類型(boolean、byte、char、short、int、float、long、double)、對象引用(reference 類型)和 returnAddress 類型(指向了一條字節碼指令的地址))所在處,如圖中的a、b。操作數棧,也就是存放的就是方法當中的各種操作數的臨時空間,又如栗子中的3、4。
動態鏈接:Class文件的常量池中存在有大量的符號引用,字節碼中的方法調用指令就以指向常量池的引用作為參數,而將部分符號引用在運行期間轉化為直接引用,這種轉化即為動態鏈接。這個解釋當中會涉及到許多概念,比如常量池、符號引用等,要想理解這些概念,就需要去了解class文件的結構,內容太多就不在這里詳細描述了。
方法出口:簡單來說,就是用于標記當前方法執行完成之后,應該返回到下一條指令執行位置。比如就上面的栗子而言,add()在執行完畢之后,就應該返回到e1.add()之后繼續執行main()后面的代碼。
上面就是對JVM棧的全面講解,還沒有完全弄懂的小伙伴可以通過觀看本站的Java零基礎教程學習更多的JVM知識。
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習