聊下JVM内存模型
轉載自?聊下JVM內存模型
?
1.?JVM內存模型
?
?
2. 程序計數器(PC)
?
每個線程都會有自己私有的程序計數器(PC)??梢钥醋魇钱斍熬€程所執行的字節碼的行號指示器。
也可以理解為下一條將要執行的指令的地址或者行號。字節碼解釋器就是通過改變這個計數器的值來選取下一條需要執行的字節碼指令,分支、 循環、 跳轉、 異常處理、 線程上下文切換,線程恢復時,都要依賴PC.
-
如果線程正在執行的是一個Java方法,PC值為正在執行的虛擬機字節碼指令的地址
-
如果線程正在執行的是Native方法,PC值為空(未定義)
?
3.虛擬機棧(VM Stack)
?
VM Stack也是線程私有的區域。他是java方法執行時的字典:它里面記錄了局部變量表、 操作數棧、 動態鏈接、 方法出口等信息。
在《java虛擬機規范》一書中對這部分的描述如下:
棧幀( Frame)是用來存儲數據和部分過程結果的數據結構,同時也被用來處理動態鏈接 (Dynamic Linking)、 方法返回值和異常分派( Dispatch Exception)。
棧幀隨著方法調用而創建,隨著方法結束而銷毀——無論方法是正常完成還是異常完成(拋出了在方法內未被捕獲的異常)都算作方法結束。
棧幀的存儲空間分配在 Java 虛擬機棧( §2.5.5)之中,每一個棧幀都有自己的局部變量表( Local Variables, §2.6.1)、操作數棧( OperandStack, §2.6.2)和指向當前方法所屬的類的運行時常量池( §2.5.5)的引用。
說白了,VM Stack是一個棧,也是一塊內存區域。
所以,他是有大小的。雖然有大小,但是一般而言,各種虛擬機的實現都支持動態擴展這部分內存。
-
如果線程請求的棧深度太大,則拋出StackOverflowError
-
如果動態擴展時沒有足夠的大小,則拋出OutOfMemoryError
?
4. 本地方法棧(Native Method Stack)
Java 虛擬機實現可能會使用到傳統的棧(通常稱之為“ C Stacks”)來支持 native 方法( 指使用 Java 以外的其他語言編寫的方法)的執行,這個棧就是本地方法棧( Native MethodStack)。
VM Stack是為執行java方法服務的,此處的Native Method Stack是為執行本地方法服務的。
此處的本地方法指定是和具體的底層操作系統層面相關的接口調用了(這部分太高高級了,不想深究……)。
《java虛擬機規范》中沒有對這部分做具體的規定。所以就由VM的實現者自由發揮了。
有的虛擬機(比如HotSpot)將VM Stack和Native Method Stack合二為一,所以VM的另一種內存區域圖就如下面所示了:
?
5.Java堆(Heap)
在 Java 虛擬機中,堆( Heap)是可供各條線程共享的運行時內存區域,也是供所有類實例和數組對象分配內存的區域。
以下是本人對《java虛擬機規范》一書中對Java堆的介紹的總結:
-
在虛擬機啟動的時候就被創建
-
是所有線程共享的內存區域
-
存儲了被自動內存管理系統所管理的各種對象
-
這些受管理的對象無需,也無法顯式地被銷毀
-
自動內存管理系統:Automatic StorageManagement System,也即是常說的”Garbage Collector(垃圾收集器)”
-
并未指明用什么具體的技術去實現自動內存管理系統
-
-
Java 堆的容量可以是固定大小的,也可以隨著程序執行的需求動態擴展,并在不需要過多空間時自動收縮
-
Java 堆所使用的內存不需要保證是連續的
-
如果實際所需的堆超過了自動內存管理系統能提供的最大容量,那 Java 虛擬機將會拋出一個OutOfMemoryError?異常
-
實現者應當提供給程序員或者最終用戶調節 Java 堆初始容量的手段
-
對于可以動態擴展和收縮 Java 堆來說,則應當提供調節其最大、最小容量的手段
-
-
所有的對象實例以及數組都要在堆上分配
?
6.方法區(Method Area)
?
方法區是由所有線程共享的內存區域。
方法區存儲的大致內容如下:
-
每一個類的結構信息
-
運行時常量池( Runtime Constant Pool)
-
字段和方法數據
-
構造函數和普通方法的字節碼內容
-
-
類、實例、接口初始化時用到的特殊方法
每一個運行時常量池都分配在 Java 虛擬機的方法區之中,在類和接口被加載到虛擬機后,對應的運行時常量池就被創建出來。
-
當創建類或接口的時候,如果構造運行時常量池所需要的內存空間超過了方法區所能提供的最大值,那 Java 虛擬機將會拋出一個?OutOfMemoryError?異常。
?
7.直接內存(Direct Memory)
?
此處的直接內存并不是由JVM管理的內存。他是利用本地方法庫直接在java堆之外申請的內存區域。
比如NIO中的DirectByteBuffer就是操作直接內存的。
直接內存的好處就是避免了在java堆和native堆直接同步數據的步驟。但是他并不是由JVM來管理的。
?
?
1.?JVM內存模型
?
?
2. 程序計數器(PC)
?
每個線程都會有自己私有的程序計數器(PC)。可以看作是當前線程所執行的字節碼的行號指示器。
也可以理解為下一條將要執行的指令的地址或者行號。字節碼解釋器就是通過改變這個計數器的值來選取下一條需要執行的字節碼指令,分支、 循環、 跳轉、 異常處理、 線程上下文切換,線程恢復時,都要依賴PC.
-
如果線程正在執行的是一個Java方法,PC值為正在執行的虛擬機字節碼指令的地址
-
如果線程正在執行的是Native方法,PC值為空(未定義)
?
3.虛擬機棧(VM Stack)
?
VM Stack也是線程私有的區域。他是java方法執行時的字典:它里面記錄了局部變量表、 操作數棧、 動態鏈接、 方法出口等信息。
在《java虛擬機規范》一書中對這部分的描述如下:
棧幀( Frame)是用來存儲數據和部分過程結果的數據結構,同時也被用來處理動態鏈接 (Dynamic Linking)、 方法返回值和異常分派( Dispatch Exception)。
棧幀隨著方法調用而創建,隨著方法結束而銷毀——無論方法是正常完成還是異常完成(拋出了在方法內未被捕獲的異常)都算作方法結束。
棧幀的存儲空間分配在 Java 虛擬機棧( §2.5.5)之中,每一個棧幀都有自己的局部變量表( Local Variables, §2.6.1)、操作數棧( OperandStack, §2.6.2)和指向當前方法所屬的類的運行時常量池( §2.5.5)的引用。
說白了,VM Stack是一個棧,也是一塊內存區域。
所以,他是有大小的。雖然有大小,但是一般而言,各種虛擬機的實現都支持動態擴展這部分內存。
-
如果線程請求的棧深度太大,則拋出StackOverflowError
-
如果動態擴展時沒有足夠的大小,則拋出OutOfMemoryError
?
4. 本地方法棧(Native Method Stack)
Java 虛擬機實現可能會使用到傳統的棧(通常稱之為“ C Stacks”)來支持 native 方法( 指使用 Java 以外的其他語言編寫的方法)的執行,這個棧就是本地方法棧( Native MethodStack)。
VM Stack是為執行java方法服務的,此處的Native Method Stack是為執行本地方法服務的。
此處的本地方法指定是和具體的底層操作系統層面相關的接口調用了(這部分太高高級了,不想深究……)。
《java虛擬機規范》中沒有對這部分做具體的規定。所以就由VM的實現者自由發揮了。
有的虛擬機(比如HotSpot)將VM Stack和Native Method Stack合二為一,所以VM的另一種內存區域圖就如下面所示了:
?
5.Java堆(Heap)
在 Java 虛擬機中,堆( Heap)是可供各條線程共享的運行時內存區域,也是供所有類實例和數組對象分配內存的區域。
以下是本人對《java虛擬機規范》一書中對Java堆的介紹的總結:
-
在虛擬機啟動的時候就被創建
-
是所有線程共享的內存區域
-
存儲了被自動內存管理系統所管理的各種對象
-
這些受管理的對象無需,也無法顯式地被銷毀
-
自動內存管理系統:Automatic StorageManagement System,也即是常說的”Garbage Collector(垃圾收集器)”
-
并未指明用什么具體的技術去實現自動內存管理系統
-
-
Java 堆的容量可以是固定大小的,也可以隨著程序執行的需求動態擴展,并在不需要過多空間時自動收縮
-
Java 堆所使用的內存不需要保證是連續的
-
如果實際所需的堆超過了自動內存管理系統能提供的最大容量,那 Java 虛擬機將會拋出一個OutOfMemoryError?異常
-
實現者應當提供給程序員或者最終用戶調節 Java 堆初始容量的手段
-
對于可以動態擴展和收縮 Java 堆來說,則應當提供調節其最大、最小容量的手段
-
-
所有的對象實例以及數組都要在堆上分配
?
6.方法區(Method Area)
?
方法區是由所有線程共享的內存區域。
方法區存儲的大致內容如下:
-
每一個類的結構信息
-
運行時常量池( Runtime Constant Pool)
-
字段和方法數據
-
構造函數和普通方法的字節碼內容
-
-
類、實例、接口初始化時用到的特殊方法
每一個運行時常量池都分配在 Java 虛擬機的方法區之中,在類和接口被加載到虛擬機后,對應的運行時常量池就被創建出來。
-
當創建類或接口的時候,如果構造運行時常量池所需要的內存空間超過了方法區所能提供的最大值,那 Java 虛擬機將會拋出一個?OutOfMemoryError?異常。
?
7.直接內存(Direct Memory)
?
此處的直接內存并不是由JVM管理的內存。他是利用本地方法庫直接在java堆之外申請的內存區域。
比如NIO中的DirectByteBuffer就是操作直接內存的。
直接內存的好處就是避免了在java堆和native堆直接同步數據的步驟。但是他并不是由JVM來管理的。
?
總結
- 上一篇: 主流的电脑配置有哪些(主流的电脑配置)
- 下一篇: 使用org.apache.commons