JVM 內(nèi)存區(qū)域

JVM 在執(zhí)行 Java 程序的過程中會把它所管理的內(nèi)存劃分為如下幾個數(shù)據(jù)區(qū)域:

程序計數(shù)器

虛擬機棧

本地方法棧

方法區(qū)


程序計數(shù)器

程序計數(shù)器是一塊很小的內(nèi)存空間,是當前線程所執(zhí)行字節(jié)碼的行號指示器,線程間私有不共享。執(zhí)行 Java 方法時計數(shù)器的值為字節(jié)碼指令的地址,執(zhí)行 Native 方法時值為空。不會出現(xiàn)OutOfMemoryError。

虛擬機棧

虛擬機棧為線程私有,生命周期與線程相同,描述 Java 方法執(zhí)行的內(nèi)存模型。方法執(zhí)行時創(chuàng)建棧幀,用于存儲局部變量表、操作數(shù)棧、方法出口等信息。

局部變量表存放了編譯器可知的基本數(shù)據(jù)類型、對象引用和 returnAddress類型(字節(jié)碼指令地址),所需內(nèi)存空間在編譯器完成分配,運行期間不改變大小。

線程請求棧深度大于虛擬機允許深度時拋出 StackOverflowError(大部分虛擬機可以動態(tài)擴容,但也允許固定長度的虛擬機棧),擴展時無法申請到足夠內(nèi)存拋出 OutOfMemoryError。

本地方法棧

本地方法棧為虛擬機執(zhí)行 Native 方法服務(wù),線程隔離。虛擬機規(guī)范中無強制規(guī)定,Sun HostSpot 將本地方法棧和虛擬機棧合二為一。能夠拋出 StackOverflowError 和 OutOfMemoryError 異常。

Java 堆

Java 堆是 JVM 所管理內(nèi)存中最大的一塊,所有線程共享,在虛擬機啟動時創(chuàng)建,用于存放對象實例,是垃圾回收的主要區(qū)域。

從內(nèi)存回收的角度可分為新生代和老年代,再細致劃分可分為 Eden 空間、From Survivor 空間 和 To Survivor 空間等。

Java 堆可以處于物理上不連續(xù)的內(nèi)存空間內(nèi),只要邏輯上連續(xù)即可。

在堆中沒有內(nèi)存完成實例分配也無法再擴展時拋出 OutOfMemoryError。

方法區(qū)

方法區(qū)由各個線程共享,用于存儲已被 JVM 加載的類信息、常量、靜態(tài)變量、即使編譯器編譯后的代碼等。

JVM 規(guī)范把方法區(qū)描述為堆的一個邏輯部分,別名 Non-Heap(目的是與 Java 堆區(qū)分開)。

JVM 規(guī)范對方法區(qū)的限制非常寬松,不需要連續(xù)內(nèi)存、固定大小或可擴展均可,還可以不實現(xiàn)垃圾回收。垃圾收集行為在這個區(qū)域較少出現(xiàn)。

方法區(qū)包含運行時常量池,Class 文件中的常量信息在類加載后存放于運行時常量池中。運行時常量池具備動態(tài)性,運行期間也可能將新的常量放入池中。

當方法區(qū)無法滿足內(nèi)存分配需求時會拋出 OutOfMemoryError。

直接內(nèi)存 *

直接內(nèi)存不是 JVM 運行時數(shù)據(jù)區(qū)的一部分,也不是 JVM 規(guī)范中定義的內(nèi)存區(qū)域,但這部分內(nèi)存會被頻繁使用,而且可能會導致 OutOfMemoryError 異常。

JDK 1.4 中新加入的NIO(New Input / Output)類引入了一種基于通道與緩沖區(qū)的 IO 方式,可以使用 Native 函數(shù)庫直接分配堆外內(nèi)存,再通過存儲在 Java 堆中的DirectByteBuffer 對象做為這塊內(nèi)存的引用進行操作。

直接內(nèi)存不受 Java 堆大小限制,但會受到本機總內(nèi)存及處理器尋址空間限制,動態(tài)擴展超出限制會拋出 OutOfMemoryError 異常。

查看原文

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容