JVM內存區域的劃分

JVM在執行程序的過程中把它管理的內存劃分爲若干個不同的區域,這些區域各有各的用處,一般來說,JVM管理的內存包含以下幾個內存區域:

在這裏插入圖片描述
這些區域有線程私有的,也有線程共享的,那麼什麼是線程私有?

由於Java是多線程是通過線程之間的相互切換以及分配處理機時間的方式實現的,所以每一時刻,一個處理器只會執行一個線程中的一條指令,因此爲了線程切換後恢復到正常執行位置,每個線程都有獨立的計數器,各計數器之間互不影響,獨立存儲,我們把這一類內存區域成爲是線程私有區域。

程序計數器(線程私有)

程序計數器記錄的是當前線程所執行的字節碼的行號指示器,如果當前線程執行的是Java方法,那麼程序計數器裏記錄的是正在執行的虛擬機字節碼指令的地址,而如果當前線程執行的是一個本地方法,那麼程序計數器爲空,由於程序計數器裏只存放當前線程所執行的字節碼的指令地址,所以不會出現OOM的情況。

Java虛擬機棧(線程私有)

虛擬機棧描述的是Java方法執行的內存模型,每個方法再執行的同時都會創建一個棧幀,用於存儲局部變量表,操作數、動態鏈接、方法出口等信息,每一個方法從調用直至執行完成的過程,就對應一個棧幀在虛擬機棧中入棧和出棧,生命週期和線程相同。

我們平時所說的棧區域,實際上指的是Java虛擬機棧中的局部變量表的區域。

局部變量表

局部變量表:存放的是編譯器可知的各種基本數據類型(8種基本數據類型),對象引用。局部變量表所需的內存分配是在編譯器就已經完成分配的,這個方法需要在幀中分配多大的內存空間完全是確定的,運行期間是不會改變局部變量表的大小的。
此區域會產生兩種異常:

1.如果線程請求的棧深度大於虛擬機所允許的棧深度(-Xss設置棧容量),將會拋出StackOverFlowError異常。
2.虛擬機在動態擴展時無法申請到足夠的內存,會拋出OOM(OutOfMemoryError)異常。

本地方法棧(線程私有)

本地方法棧與虛擬機棧的作用完全一樣,他倆的區別無非是本地方法棧爲虛擬機使用的Native方法服務,而虛擬機棧爲JVM執行的Java方法服務。
在HotSpot虛擬機中,本地方法棧與虛擬機棧是同一塊內存區域。

Java堆(線程共享)

Java堆是JVM管理的最大的一塊內存區域了,也是一個線程共享的區域,在JVM規範中寫到所有的對象以及數組都要在堆上分配。Java堆也是垃圾回收器管理的主要區域,通常也稱作是GC堆,根據JVM規範規定的內容,Java堆可以處於物理上不連續的內存空間中,Java堆在主流的虛擬機上都是可擴展的(-Xmx設置最大值,-Xms設置最小值)

如果在堆中沒有足夠的內存完成實例分配或者堆也無法拓展時,就會出現OOM。

方法區(線程共享)

方法區與Java堆一樣是各個線程共享的區域,它用於存儲已被虛擬機加載的類信息,常量和靜態變量、即時編譯器編譯後的代碼數據,在JDK8以前的HotSpot虛擬機中,方法區也被稱爲"永久代"(JDK8已經被元空間取
代)。永久代並不意味着數據進入方法區就永久存在,此區域的內存回收主要是針對常量池的回收以及對類型的卸載。
JVM規定,當方法去無法滿足內存分配需求時,就是出現OOM。

運行時常量區

運行時常量區是方法區的一部分,存放字面量和符號引用。

字面量:字符串(JDK1.7以後移動到堆中)、final常量、基本類型的值
符號引用:類和結構的完全限定名、字段的名稱和描述符、方法的名稱和描述符。

在這裏插入圖片描述

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