JVM虛擬機內存劃分
JVM內存結構劃分圖
運行時數據區
程序計數器
當前線程所執行的字節碼的行號指示器
- 線程私有
- 線程執行Java方法,記錄正在執行的虛擬機字節碼指令地址
- 線程執行Native方法,則計數器值爲空
- 此內存區域是Java虛擬機規範中唯一一個沒有規定任何OutOfMemoryError情況的區域
Java虛擬機棧
虛擬機棧描述Java方法執行的內存模型
- Java虛擬機棧內存私有,生命週期與線程相同
- 每個方法執行會創建棧幀,存儲局部變量表、操作數棧、動態鏈接、方法出口等信息
- 棧幀局部變量表存放了編譯期可預知的各種基本數據類型(boolean、byte、char、short、int、float、long、double)、對象引用、returnAddress類型(指向了一條字節碼指令的地址)
- 其中64位長度的long和double類型佔用2個局部變量空間(Slot),其它佔用一個。局部變量表所需空間在編譯器分配,當進入一個方法時,這個方法需要在幀中分配多大的局部變量空間是確定的
- 線程請求棧深度大於虛擬機棧所允許深度拋出StackOverflowError異常
- 若虛擬機棧可動態擴展又無法申請到足夠內存拋出OutOfMemoryError異常
本地方法棧
與虛擬機方法棧的區別:
虛擬機棧爲虛擬機執行Java方法(也就是字節碼)服務,而本地方法棧則爲虛擬機使用到的Native方法服務
本地方法棧也會拋出StackOverflowError和OutOfMemoryError異常
Java堆
Java堆是虛擬機管理的內存最大一塊區域
- 所有線程共享
- 存放對象實例,幾乎所有對象實例與數組都在這裏分配內存
- 是垃圾收集器管理的主要區域,常稱GC堆
- Java堆可以處於物理不連續內存,邏輯連續即可
- 虛擬機棧大小可以通過參數-Xmx和-Xms控制
- 內存不足會拋出OutOfMemoryError異常
方法區
用於存儲已經被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼數據
- 各個線程共享的內存區域,別名Non-Heap(非堆)
- 當方法區內存無法滿足分配拋出OutOfMemory異常
- 垃圾收集在這個區域很少出現
運行時常量池
- 運行時常量池(Runtime Constant Pool)是方法區的一部分,Class文件除了有類的版本、字段、方法、接口等描述信息外,還有一項是常量池,用於存放編譯器生成的各種字面量和符號引用,這部分內容將在類加載後進入方法區的運行時常量池中存放
- 運行時常量池是方法區的一部分,受到內存方法區的限制,內存不足分配會拋出OutOfMemoryError異常
直接內存
不屬於虛擬機運行時數據區,也不是Java虛擬機規範中定義的內存區域
- NIO緩衝區使用Native函數庫直接分配堆外內存,通過一個存儲在Java堆中的DirectByteBuffer對象作爲這塊內存的引用進行操作
- 受物理內存大小限制,內存不夠 分配會拋出OutOfMemoryError異常