Java虛擬機結構:運行時數(shù)據(jù)區(qū)
Java虛擬機可以支持多條線程同時執(zhí)行,每一條Java虛擬機線程都有自己的pc寄存器。再任意時刻,一條Java虛擬機線程只會執(zhí)行一個方法的代碼,這個正在被線程執(zhí)行的方法稱為該線程的當前方法。
如果這個方法不是native的,那pc寄存器就保存Java虛擬機正在執(zhí)行的字節(jié)碼指令的地址,如果該方法是native的,那pc寄存器的值是undefined。pc寄存器的容量至少應當能保存一個returnAddress類型的數(shù)據(jù)或者一個與平臺相關的本地指針的值。
Java虛擬機棧
每一條Java虛擬機線程都有自己私有的Java虛擬機棧,這個棧與線程同時創(chuàng)建,用于存儲棧幀。Java虛擬機棧用于存儲局部變量與一些尚未算好的結果。另外它在方法調用和返回中也扮演了很重要的角色。因為除了棧幀的出棧和入棧之外,Java虛擬機棧不會再受其他因素的影響,所以棧幀可以在堆中分配,Java虛擬機棧所使用的內存不需要保證是連續(xù)的。
Java虛擬機實現(xiàn)應當提供給程序員或者最終用戶調節(jié)虛擬機棧初始容量的手段,對于可以動態(tài)擴展和收縮Java虛擬機棧來說,則應當提供調節(jié)其***、最小容量的手段。
Java虛擬機棧可能發(fā)生如下異常情況:
- 如果線程請求分配的棧容量超過Java虛擬機棧允許的***容量,Java虛擬機將會拋出一個StackOverflowError異常;
- 如果Java虛擬機棧可以動態(tài)擴展,并且在嘗試擴展的時候無法申請到足夠的內存,或者在創(chuàng)建新的線程時沒有足夠的內存去創(chuàng)建對應的虛擬機棧,那Java虛擬機將會拋出一個OutOfMemoryError異常。
Java堆
在Java虛擬機中,堆是可供各個線程共享的運行時內存區(qū)域, 也是供所有類實例和數(shù)組對象分配內存的區(qū)域。
Java堆在虛擬機啟動的時候就被創(chuàng)建,它存儲了被自動管理系統(tǒng)(也即常說的垃圾收集器)所管理的各種對象,這些受管理的對象無需也無法顯式地銷毀。虛擬機實現(xiàn)者可以根據(jù)系統(tǒng)的實際需要來選擇自動內存管理技術。Java堆的容量可以是固定的,也可以隨著程序執(zhí)行的需求動態(tài)擴展,并在不需要過多空間時自動收縮。Java堆所使用的內存不需要保證是連續(xù)的。
Java虛擬機實現(xiàn)應當提供給程序員或者最終用戶調節(jié)Java堆初始容量的手段,對于可以動態(tài)擴展和收縮Java堆來說,則應當提供調節(jié)其***、最小容量的手段。
Java堆可能發(fā)生如下異常:
- 如果實際所需的堆超過了自動內存管理系統(tǒng)能提供的***容量,那Java虛擬機將會拋出一個OutOfMemoryError異常。
方法區(qū)
在Java虛擬機中,方法區(qū)是可供各個線程共享的運行時內存區(qū)域。方法區(qū)與傳統(tǒng)語言中的編譯代碼存儲區(qū)或者操作系統(tǒng)進程的正文段的作用非常相似,它存儲了每一個類的結構信息,例如,運行時常量池、字段和方法數(shù)據(jù)、構造函數(shù)和普通方法的字節(jié)碼內容,還包括一些在類、實例、接口初始化時用到的特殊方法。
方法區(qū)在虛擬機啟動的時候創(chuàng)建,雖然方法區(qū)是堆的邏輯組成部分,但是簡單的虛擬機實現(xiàn)可以選擇在這個區(qū)域不實現(xiàn)垃圾收集與壓縮。方法區(qū)的容量可以是固定的,也可以隨著程序執(zhí)行的需求動態(tài)擴展,并在不需要過多空間時自動收縮。方法區(qū)在實際內存空間中可以是不連續(xù)的。
Java虛擬機實現(xiàn)應當提供給程序員或者最終用戶調節(jié)方法區(qū)初始容量的手段,對于可以動態(tài)擴展和收縮方法區(qū)來說,則應當提供調節(jié)其***、最小容量的手段。
方法區(qū)可能發(fā)生如下異常情況:
-
如果方法區(qū)的內存空間不能滿足內存分配請求,那么Java虛擬機將拋出一個OutOfMemoryError異常。
運行時常量池
運行時常量池是class文件中每一個類或接口的常量池表的運行時表示形式,它包括了若干種不同的常亮,從編譯期可知的數(shù)值字面量到必須在運行期解析后才能獲得的方法或字段引用。運行時常量池類似于傳統(tǒng)語言中的符號表,不過它存儲數(shù)據(jù)的范圍比通常意義上的符號表要更為廣泛。
每一個運行時常量池都在Java虛擬機的方法區(qū)中分配,在加載類和接口到虛擬機后,就創(chuàng)建對應的運行時常量池。
在創(chuàng)建類和接口的運行時常量池時,可能會發(fā)生如下異常情況:
- 當創(chuàng)建類或接口時,如果構造運行時常亮池所需要的內存空間超過了方法區(qū)所能提供的***值,那么Java虛擬機將會拋出一個OutOfMemoryError異常。
本地方法棧
Java虛擬機實現(xiàn)可能會使用到傳統(tǒng)的棧來支持native方法的執(zhí)行,這個棧就是本地方法棧。當Java虛擬機使用其他語言來實現(xiàn)指令集解釋器時,也可以使用本地方法棧。如果Java虛擬機不支持native方法,或是本身不依賴傳統(tǒng)棧,那么可以不提供本地方法棧,如果支持本地方法棧,那這個棧一般會在線程創(chuàng)建的時候按線程分配。
Java虛擬機規(guī)范允許本地方法棧實現(xiàn)成固定大小或者根據(jù)計算來動態(tài)擴展和收縮。如果采用固定大小的本地方法棧,那么每一個線程的本地方法棧容量可以在創(chuàng)建棧的時候獨立選定。
Java虛擬機實現(xiàn)應當提供給程序員或者最終用戶調節(jié)本地方法棧初始容量的手段,對于可以動態(tài)擴展和收縮方法區(qū)來說,則應當提供調節(jié)其***、最小容量的手段。
本地方法棧可能發(fā)生如下異常情況:
- 如果線程請求分配的棧容量超過本地方法棧允許的***容量,Java虛擬機將會拋出一個StackOverflowError異常。
- 如果本地方法棧可以動態(tài)擴展,并且在嘗試擴展的時候無法申請到足夠的內存,或者在創(chuàng)建新的線程時沒有足夠的內存去創(chuàng)建對應的本地方法棧,那么Java虛擬機將會拋出一個OutOfMemoryError異常。