每一個線程都會有本身私有的程序計數器(PC)。能夠看做是當前線程所執行的字節碼的行號指示器。
也能夠理解爲下一條將要執行的指令的地址或者行號。字節碼解釋器就是經過改變這個計數器的值來選取下一條須要執行的字節碼指令,分支、 循環、 跳轉、 異常處理、 線程上下文切換,線程恢復時,都要依賴PC.java
若是線程正在執行的是一個Java方法,PC值爲正在執行的虛擬機字節碼指令的地址程序員
若是線程正在執行的是Native方法,PC值爲空(未定義)數組
VM Stack也是線程私有的區域。他是java方法執行時的字典:它裏面記錄了局部變量表、 操做數棧、 動態連接、 方法出口等信息。數據結構
在《java虛擬機規範》一書中對這部分的描述以下:app
棧幀( Frame)是用來存儲數據和部分過程結果的數據結構,同時也被用來處理動態連接 (Dynamic Linking)、 方法返回值和異常分派( Dispatch Exception)。
棧幀隨着方法調用而建立,隨着方法結束而銷燬——不管方法是正常完成仍是異常完成(拋出了在方法內未被捕獲的異常)都算做方法結束。
棧幀的存儲空間分配在 Java 虛擬機棧( §2.5.5)之中,每個棧幀都有本身的局部變量表( Local Variables, §2.6.1)、操做數棧( OperandStack, §2.6.2)和指向當前方法所屬的類的運行時常量池( §2.5.5)的引用。ide
說白了,VM Stack是一個棧
,也是一塊內存區域
。
因此,他是有大小的。雖然有大小,可是通常而言,各類虛擬機的實現都支持動態擴展這部份內存。函數
若是線程請求的棧深度太大,則拋出StackOverflowError
spa
若是動態擴展時沒有足夠的大小,則拋出OutOfMemoryError
操作系統
Java 虛擬機實現可能會使用到傳統的棧(一般稱之爲「 C Stacks」)來支持 native 方法( 指使用 Java 之外的其餘語言編寫的方法)的執行,這個棧就是本地方法棧( Native MethodStack)。線程
VM Stack是爲執行java方法服務的,此處的Native Method Stack是爲執行本地方法服務的。
此處的本地方法指定是和具體的底層操做系統層面相關的接口調用了(這部分過高高級了,不想深究……)。
《java虛擬機規範》中沒有對這部分作具體的規定。因此就由VM的實現者自由發揮了。
有的虛擬機(好比HotSpot)將VM Stack和Native Method Stack合二爲一,因此VM的另外一種內存區域圖就以下面所示了:
在 Java 虛擬機中,堆( Heap)是可供各條線程共享的運行時內存區域,也是供全部類實例和數組對象分配內存的區域。
如下是本人對《java虛擬機規範》一書中對Java堆的介紹的總結:
在虛擬機啓動的時候就被建立
是全部線程共享的內存區域
存儲了被自動內存管理系統所管理的各類對象
這些受管理的對象無需,也沒法顯式地被銷燬
自動內存管理系統:Automatic StorageManagement System,也便是常說的」Garbage Collector(垃圾收集器)」
並未指明用什麼具體的技術去實現自動內存管理系統
Java 堆的容量能夠是固定大小的,也能夠隨着程序執行的需求動態擴展,並在不須要過多空間時自動收縮
Java 堆所使用的內存不須要保證是連續的
若是實際所需的堆超過了自動內存管理系統能提供的最大容量,那 Java 虛擬機將會拋出一個OutOfMemoryError
異常
實現者應當提供給程序員或者最終用戶調節 Java 堆初始容量的手段
對於能夠動態擴展和收縮 Java 堆來講,則應當提供調節其最大、最小容量的手段
全部的對象實例以及數組都要在堆上分配
方法區是由全部線程共享的內存區域。
方法區存儲的大體內容以下:
每個類的結構信息
運行時常量池( Runtime Constant Pool)
字段和方法數據
構造函數和普通方法的字節碼內容
類、實例、接口初始化時用到的特殊方法
每個運行時常量池都分配在 Java 虛擬機的方法區之中,在類和接口被加載到虛擬機後,對應的運行時常量池就被建立出來。
當建立類或接口的時候,若是構造運行時常量池所須要的內存空間超過了方法區所能提供的最大值,那 Java 虛擬機將會拋出一個 OutOfMemoryError
異常。
此處的直接內存並非由JVM管理的內存。他是利用本地方法庫
直接在java堆以外申請的內存區域。
好比NIO中的DirectByteBuffer
就是操做直接內存的。
直接內存的好處就是避免了在java堆和native堆直接同步數據的步驟。可是他並非由JVM來管理的。