【Java虛擬機器規範】Java虛擬機器結構:執行時資料區
Java虛擬機器可以支援多條執行緒同時執行,每一條Java虛擬機器執行緒都有自己的pc暫存器。再任意時刻,一條Java虛擬機器執行緒只會執行一個方法的程式碼,這個正在被執行緒執行的方法稱為該執行緒的當前方法。
如果這個方法不是native的,那pc暫存器就儲存Java虛擬機器正在執行的位元組碼指令的地址,如果該方法是native的,那pc暫存器的值是undefined。pc暫存器的容量至少應當能儲存一個returnAddress型別的資料或者一個與平臺相關的本地指標的值。
Java虛擬機器棧
每一條Java虛擬機器執行緒都有自己私有的Java虛擬機器棧,這個棧與執行緒同時建立,用於儲存棧幀。Java虛擬機器棧用於儲存區域性變數與一些尚未算好的結果。另外它在方法呼叫和返回中也扮演了很重要的角色。因為除了棧幀的出棧和入棧之外,Java虛擬機器棧不會再受其他因素的影響,所以棧幀可以在堆中分配,Java虛擬機器棧所使用的記憶體不需要保證是連續的。
Java虛擬機器實現應當提供給程式員或者終端使用者調節虛擬機器棧初始容量的手段,對於可以動態擴充套件和收縮Java虛擬機器棧來說,則應當提供調節其最大、最小容量的手段。
Java虛擬機器棧可能發生如下異常情況:
- 如果執行緒請求分配的棧容量超過Java虛擬機器棧允許的最大容量,Java虛擬機器將會丟擲一個StackOverflowError異常;
- 如果Java虛擬機器棧可以動態擴充套件,並且在嘗試擴充套件的時候無法申請到足夠的記憶體,或者在建立新的執行緒時沒有足夠的記憶體去建立對應的虛擬機器棧,那Java虛擬機器將會丟擲一個OutOfMemoryError異常。
Java堆
在Java虛擬機器中,堆是可供各個執行緒共享的執行時記憶體區域,也是供所有類例項和陣列物件分配記憶體的區域。
Java堆在虛擬機器啟動的時候就被建立,它儲存了被自動管理系統(也即常說的垃圾收集器)所管理的各種物件,這些受管理的物件無需也無法顯式地銷燬。虛擬機器實現者可以根據系統的實際需要來選擇自動記憶體管理技術。Java堆的容量可以是固定的,也可以隨著程式執行的需求動態擴充套件,並在不需要過多空間時自動收縮。Java堆所使用的記憶體不需要保證是連續的。
Java虛擬機器實現應當提供給程式設計師或者終端使用者調節Java堆初始容量的手段,對於可以動態擴充套件和收縮Java堆來說,則應當提供調節其最大、最小容量的手段。
Java堆可能發生如下異常:
- 如果實際所需的堆超過了自動記憶體管理系統能提供的最大容量,那Java虛擬機器將會丟擲一個OutOfMemoryError異常。
方法區
在Java虛擬機器中,方法區是可供各個執行緒共享的執行時記憶體區域。方法區與傳統語言中的編譯程式碼儲存區或者作業系統程序的正文段的作用非常相似,它儲存了每一個類的結構資訊,例如,執行時常量池、欄位和方法資料、建構函式和普通方法的位元組碼內容,還包括一些在類、例項、介面初始化時用到的特殊方法。
方法區在虛擬機器啟動的時候建立,雖然方法區是堆的邏輯組成部分,但是簡單的虛擬機器實現可以選擇在這個區域不實現垃圾收集與壓縮。方法區的容量可以是固定的,也可以隨著程式執行的需求動態擴充套件,並在不需要過多空間時自動收縮。方法區在實際記憶體空間中可以是不連續的。
Java虛擬機器實現應當提供給程式設計師或者終端使用者調節方法區初始容量的手段,對於可以動態擴充套件和收縮方法區來說,則應當提供調節其最大、最小容量的手段。
方法區可能發生如下異常情況:
- 如果方法區的記憶體空間不能滿足記憶體分配請求,那麼Java虛擬機器將丟擲一個OutOfMemoryError異常。
執行時常量池
執行時常量池是class檔案中每一個類或介面的常量池表的執行時表示形式,它包括了若干種不同的常亮,從編譯期可知的數值字面量到必須在執行期解析後才能獲得的方法或欄位引用。執行時常量池類似於傳統語言中的符號表,不過它儲存資料的範圍比通常意義上的符號表要更為廣泛。
每一個執行時常量池都在Java虛擬機器的方法區中分配,在載入類和介面到虛擬機器後,就建立對應的執行時常量池。
在建立類和介面的執行時常量池時,可能會發生如下異常情況:
- 當建立類或介面時,如果構造執行時常亮池所需要的記憶體空間超過了方法區所能提供的最大值,那麼Java虛擬機器將會丟擲一個OutOfMemoryError異常。
本地方法棧
Java虛擬機器實現可能會使用到傳統的棧來支援native方法的執行,這個棧就是本地方法棧。當Java虛擬機器使用其他語言來實現指令集直譯器時,也可以使用本地方法棧。如果Java虛擬機器不支援native方法,或是本身不依賴傳統棧,那麼可以不提供本地方法棧,如果支援本地方法棧,那這個棧一般會線上程建立的時候按執行緒分配。
Java虛擬機器規範允許本地方法棧實現成固定大小或者根據計算來動態擴充套件和收縮。如果採用固定大小的本地方法棧,那麼每一個執行緒的本地方法棧容量可以在建立棧的時候獨立選定。
Java虛擬機器實現應當提供給程式設計師或者終端使用者調節本地方法棧初始容量的手段,對於可以動態擴充套件和收縮方法區來說,則應當提供調節其最大、最小容量的手段。
本地方法棧可能發生如下異常情況:
- 如果執行緒請求分配的棧容量超過本地方法棧允許的最大容量,Java虛擬機器將會丟擲一個StackOverflowError異常。
- 如果本地方法棧可以動態擴充套件,並且在嘗試擴充套件的時候無法申請到足夠的記憶體,或者在建立新的執行緒時沒有足夠的記憶體去建立對應的本地方法棧,那麼Java虛擬機器將會丟擲一個OutOfMemoryError異常。