Java虚拟机栈介绍
與程序計數器一樣,Java虛擬機棧(Java Virtual Machine Stack)也是線程私有的,它的生命周期 與線程相同。虛擬機棧描述的是Java方法執行的線程內存模型:每個方法被執行的時候,Java虛擬機都 會同步創建一個棧幀[1](Stack Frame)用于存儲局部變量表、操作數棧、動態連接、方法出口等信 息。每一個方法被調用直至執行完畢的過程,就對應著一個棧幀在虛擬機棧中從入棧到出棧的過程。
經常有人把Java內存區域籠統地劃分為堆內存(Heap)和棧內存(Stack),這種劃分方式直接繼 承自傳統的C、C++程序的內存布局結構,在Java語言里就顯得有些粗糙了,實際的內存區域劃分要比 這更復雜。不過這種劃分方式的流行也間接說明了程序員最關注的、與對象內存分配關系最密切的區 域是“堆”和“棧”兩塊。其中,“堆”在稍后筆者會專門講述,而“棧”通常就是指這里講的虛擬機棧,或 者更多的情況下只是指虛擬機棧中局部變量表部分。
局部變量表存放了編譯期可知的各種Java虛擬機基本數據類型(boolean、byte、char、short、int、 float、long、double)、對象引用(reference類型,它并不等同于對象本身,可能是一個指向對象起始 地址的引用指針,也可能是指向一個代表對象的句柄或者其他與此對象相關的位置)和returnAddress 類型(指向了一條字節碼指令的地址)。
這些數據類型在局部變量表中的存儲空間以局部變量槽(Slot)來表示,其中64位長度的long和 double類型的數據會占用兩個變量槽,其余的數據類型只占用一個。局部變量表所需的內存空間在編 譯期間完成分配,當進入一個方法時,這個方法需要在棧幀中分配多大的局部變量空間是完全確定 的,在方法運行期間不會改變局部變量表的大小。請讀者注意,這里說的“大小”是指變量槽的數量, 虛擬機真正使用多大的內存空間(譬如按照1個變量槽占用32個比特、64個比特,或者更多)來實現一 個變量槽,這是完全由具體的虛擬機實現自行決定的事情。
在《Java虛擬機規范》中,對這個內存區域規定了兩類異常狀況:如果線程請求的棧深度大于虛 擬機所允許的深度,將拋出StackOverflowError異常;如果Java虛擬機棧容量可以動態擴展[2],當棧擴 展時無法申請到足夠的內存會拋出OutOfMemoryError異常。
[1] 棧幀是方法運行期很重要的基礎數據結構,在本書的第8章中還會對幀進行詳細講解。 [2] HotSpot虛擬機的棧容量是不可以動態擴展的,以前的Classic虛擬機倒是可以。所以在HotSpot虛擬 機上是不會由于虛擬機棧無法擴展而導致OutOfMemoryError異常——只要線程申請棧空間成功了就不 會有OOM,但是如果申請時就失敗,仍然是會出現OOM異常的,后面的實戰中筆者也演示了這種情 況。本書第2版時這里的描述是有誤的,請閱讀過第2版的讀者特別注意
總結
以上是生活随笔為你收集整理的Java虚拟机栈介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++ 常量引用
- 下一篇: oracle用户手册在哪里,Oracle