JVM內存模型

程序計數器(線程私有):

也有稱作PC寄存器。每個線程都有一個私有的程序計數器,程序計數器存放的是當前線程所執行的字節碼的行號指示器。當CPU需要執行指令時,需要從程序計數器中得到當前需要執行的指令所在存儲單元的地址,然後根據得到的地址獲取到指令,在得到指令之後,程序計數器便自動加1或者根據轉移指針得到下一條指令的地址,如此循環,直至執行完所有的指令。程序計數器也控制着程序的分支、循環、跳轉、異常、恢復等。Java多線程是通過線程輪流切換並分配處理器執行時間來實現的,一個核心在一個時刻只能執行一條線程的指令,所以爲了線程切換後能恢復到原來位置,每個線程都需要一個程序計數器(線程私有)

 

Java虛擬機棧/Java棧(線程私有):

1、在創建線程的時候會創建對應線程的虛擬機棧。棧中存放的是一個個的棧幀,當有一個方法被執行時,就會創建一個棧幀,棧幀存儲着局部變量表、操作棧、動態鏈接、方法返回地址等。

2、局部變量表包含基本類型、對象引用(引用指針)、returnAddress類型等;
且局部變量表所需的內存空間在編譯期間完成分配,在方法運行期間不會改變局部變量表的大小。

3、如果線程請求的棧深度大於虛擬機所允許的深度,將拋出StackOverflowError異常,但大部分虛擬機的棧深度可動態擴展,當擴展無法申請到足夠的內存時OutOfMemoryError

 

本地方法棧(線程私有):

1、與Java棧的作用和原理相似,區別是:Java棧爲虛擬機執行Java方法服務,而本地方法棧爲虛擬機用到的Native方法服務.

2、有的虛擬機(如Sun HotSpot虛擬機)直接將本地方法棧和虛擬機棧合二爲一

3、本地方法棧一樣會拋出StackOverflowError和OutOfMemoryError異常

 

Java堆(線程共享):

1、Java堆是Java虛擬機所管理的內存中最大的一塊

2、Java堆在虛擬機啓動時創建,目的是存放對象實例,幾乎所有的對象實例和數組都在這裏分配

3、Java堆是垃圾收集器管理的主要區域,因此很多時候也被成爲“GC堆”

4、從內存回收角度來看,Java堆可以細分爲新生代和老年代(分代收集算法);再細緻一點有Eden控件、From Survicor空間、To Survicor空間。

5、從內存分配角度來看,線程共享的Java堆可能劃分出多個線程私有的分配緩衝區。

6、Java堆可以處於物理上不連續的內存空間,可擴展;如果堆中沒有內存完成實例分配,且無法再擴展時,將會拋出OutOfMemoryError異常

 

方法區(線程共享):

1、用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等

2、不需要連續的內存、可擴展,也可以選擇不實現垃圾收集,垃圾收集在這個區域較少出現

3、這個區域的內存回收目標主要是針對常量池的回收和對類型的卸載,但是回收的條件苛刻,可能因爲對該區域未完全回收而導致內存泄漏

4、當方法區無法滿足內存分配需求時,將拋出OutOfMemoryError異常

 

運行時常量池(方法區的一部分):

1、Class文件中除了有類的版本、字段、方法、接口等描述信息外,還有一項信息是常量池,用於存放編譯器生成的各種字面量和符號引用,這部分內容將在類加載後放到方法區的運行時常量池。

2、一般來說,除了保存Class文件中描述的符號引用外,還會把翻譯出來的直接引用

也存儲在運行時常量池中。

3、運行期間也可能將新的常量放入池中,如String類的intern()方法

4、常量池無法再申請到內存的時候,將拋出OutOfMemoryError異常

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章