Java虛擬機運行時數據區

運行時數據區域

java虛擬機在執行java程序過程中會把他所管理的內存劃分爲若干個不同的數據區域。

java虛擬機運行時數據區

方法區(線程共享區),虛擬機棧,本地方法棧,堆(線程共享區),程序計數器

1.程序計數器

程序計數器是一塊較小的內存空間,他可以看作當前線程所執行的字節碼指示器。每條線程都需要有一個獨立的程序計數器,各條線程之間計數器互不影響,獨立儲存,我們稱這類內存區域爲“線程私有”的內存。
若線程執行的時java方法,計數器記錄的是正在執行的虛擬機字節碼的指令地址。若執行的是native方法,則這個計數器爲空。此內存區域是唯一一個在java虛擬機規範中沒有規定任何內存溢出情況的區域。

2.java虛擬機棧

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

局部變量表存放着編譯期可知的基本數據類型,對象引用類型,何returnAddress類型(指向了一條字節碼指令的地址)。

long和double類型數據會佔用2個局部變量空間(slot),其餘的佔用一個。局部變量表所需的內存在編譯期間完成分配。

java虛擬機此內存區域規定了兩種異常狀況:線程請求棧深度大於虛擬機允許的深度則拋出 stackoverflow異常。若虛擬機棧可以動態擴容,但是申請的內存無法足夠申請的時候,會拋出outofmemoryerror異常。

3.本地方法棧

本地方法棧執行native方法,其與java虛擬機棧的作用相似。異常拋出的規範也和虛擬機棧一樣。

4.java堆

大多數情況下,java堆是java虛擬機中最大的一塊內存,在虛擬機啓動時創建,唯一的作用就是存放java的實例對象,幾乎所有的實例都在java堆中分配,不過隨着jit編譯器的發展和逃逸技術的成熟,棧上分配,標量替換導致這方面會發生一系列變化。

java堆是垃圾收集器的主要管理區域,因此很多時候也被稱爲GC堆,從內存回收角度看,java堆被分爲新生代和老年代。從內存分配的角度看,線程共享的java堆中可能劃分出多個線程私有的分配緩衝區。

java堆可以處於物理內存中不連續的內存空間中,只要邏輯上連續即可,就像我們的磁盤空間一樣。既可以固定大小,也可以擴展。

java虛擬機規定此區域拋出異常爲outofmemoryerror。

5.方法區

方法區和java堆一樣,,是各個線程共享的內存區域,他用於儲存已被虛擬機加載的類信息,常量,靜態變量,即使編譯器編譯後的代碼數據。可以不實現垃圾收集,

java虛擬機規範此區域的異常有outofmemoryerror異常。

5.1.運行時常量池

運行時常量池是方法區的一部分,class文件除了有類的版本,字段,方法,接口等描述信息還有一項是常量池。用於存放編譯器生成的各種字面量和符號引用,這部分內容將在類加載後進入運行時常量池中存在放。一般來說除了保存class文件中描述的符號引用外,還會把翻譯出來的直接引用也存儲在運行時常量池中。

運行時常量池相對class文件常量池還具備動態性,常量並不一定要編譯期才能產生,並非class文件的常量池才能放入,運行期間也可能將新的常量放入。

java虛擬機規範的異常和java方法區一樣。

6.直接內存

直接內存並不是虛擬機運行時數據區的一部分,也不是java虛擬機規範中定義的內存區域。本機的直接內存的分配不會收到java堆的影響。但是會受到本機內存大小和處理器尋址空間的限制。

例如NIO類,使用native函數直接分配堆外內存。

如果忽略了直接內存,虛擬機配置內存的時候,使各個內存總和大於內存限制。出現outofmemoryerror異常。

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