java虛擬機 運行時數據區域

運行時數據區域如圖:

這裏寫圖片描述

下面介紹各個區域:

程序計數器:

程序計數器是java虛擬機內存中較小的一塊內存區域。它可以是當前線程所執行的字節碼的行號指示器。在虛擬機的概念模型裏,字節碼解釋器工作時就是通過改變程序計數器的值來選取下一條執行的字節碼指令。分支、循環、跳轉、行號指示器、線程恢復等基本功能都是依賴這個程序計數器來完成。

java虛擬機多線程是通過線程輪流切換並分配處理器執行時間的方式來實現。在任何一個確定的時刻,一個處理器都只會執行線程中的一條指令。因此線程爲了恢復到正確的執行位置,每條線程都需要一個單獨的程序計數器。因此程序計數器是線程私有的內存區域。

當java線程執行的是一個java方法時,程序計數器存放的是正在執行的虛擬機字節碼指令的地址。
如果執行的本地方法,程序計數器的值爲空(Undefined)。
此內存區域是虛擬機規範中沒有規定任何OutOfMemoryError的區域。

虛擬機棧

也是java虛擬機中線程私有的內存區域。
它描述的是java方法執行的內存模型。
每個方法執行的同時都會創建一個棧幀,用於存放局部變量表、操作數棧、動態連接、方法出口等信息。
每個java方法從調用直至調用完成的過程,都對應java虛擬機棧中棧幀的入棧到出棧的過程。

局部變量表存放了編譯器可知的各種基本數據類型,對象引用和 returnAddress類型,64位長度的double 和float類型需要佔用兩個局部變量空間(slot),其餘的類型佔用一個slot。

局部變量表所需內存空間在編譯期間完成分配,當進入一個方法時,這個方法需要在棧幀中分配多大的局部變量空間是完全確定的,在方法運行期間不會改變局部變量表的大小。

在java虛擬機規範中,對這個區域規定了兩種異常狀況:
如果線程請求的棧深度大於虛擬機所允許的深度,將拋出StackOverflowError異常;
如果虛擬機棧可以動態擴展,那麼在擴展時無法申請到足夠的內存,將拋出OutOfmemoryError異常。

本地方法棧

本地方法棧也是線程私有的內存區域,和虛擬機棧作用類似,只是當程序調用的是java本地方法時,棧幀在這個地方創建。

本地方法棧也會拋出stackOverflowError和outOfmemoryError異常。

是java虛擬機內存中最大內存區域。
是所有線程共享的內存區域。此區域的唯一目的是存放java對象的實例。
java堆是垃圾收集器管理的主要內存區域。
java堆分爲老年代和新生代
還可以細分爲:Eden空間、 From Survivor 空間、To Survivor空間。
堆的大小可以由參數 -Xmx -Xms來控制。
當無法繼續擴展時,將拋出OutOfMemoryError異常。

方法區

方法區和堆內存一樣,都是線程共享的內存區域。
用來存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據。

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

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

運行時常量池相對於Class文件常量池的另外一個重要特徵是具備動態性,java語言並不要求常量一定只有編譯期才能產生,也就是並非預置入Class文件中常量池的內容才能進入方法區運行時常量池,運行期間也可能將新的常量池放入池中。

直接內存

直接內存並不是虛擬機運行時數據區的一部分,也不是java虛擬機規範的中定義的內存區域。但是這部分內存也會被頻繁地是喲個,而且也可能導致OutofMemoryError的異常。

在JDK1.4 中新加入了NIO,引入了一種基於通道與緩衝區的IO方式,它惡意使用Native函數庫直接分配堆外內存,然後通過一個存儲在java堆中的DirectByteBuffer對象作爲這塊內存的引用進行操作,這樣能在一些場景彙總顯著提高性能,因爲避免了在Java堆和Native堆中來回複製數據。

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