JVM的記憶體分區 這篇文章嘗試討論清楚JVM的記憶體分區情況。 1. JVM的記憶體和系統記憶體的關係 下圖是對系統記憶體及JVM記憶體的大致描繪 對大多數操作系統,記憶體可以分為物理記憶體RAM及Swap(交換區)兩大部分,Swap Space在物理上是一塊獨立的磁碟區域,當操作系統發現記憶體不夠使用時,便開始使 ...
JVM的記憶體分區
這篇文章嘗試討論清楚JVM的記憶體分區情況。
1. JVM的記憶體和系統記憶體的關係
下圖是對系統記憶體及JVM記憶體的大致描繪
對大多數操作系統,記憶體可以分為物理記憶體RAM及Swap(交換區)兩大部分,Swap Space在物理上是一塊獨立的磁碟區域,當操作系統發現記憶體不夠使用時,便開始使用交換區。
在系統層面,Linux系統的記憶體大致可以劃分為:
- BIN,內核引導記憶體
- Kernel Space(內核記憶體),操作系統進行程式調度,記憶體分配,硬體資源管理等動作需要的記憶體
- User Space(用戶記憶體),提供給各個進程使用
一個JAVA程式開始運行之後,是存在於系統之上的一個進程。這個進程所占用的記憶體由JVM管理。
2. JVM記憶體的劃分
JVM的記憶體可以劃分為以下幾個主要部分:
- Program Counter Register,程式計數器,線程私有,是一塊較小的記憶體空間,可以理解為當前線程執行位元組碼的行號指示器。
- Method Area,方法區,由各線程共用,用於載入類信息,常量,靜態變數等數據。在HotSpot虛擬機的實現中,稱這部分記憶體為Permanent Generation(永久代),這使得虛擬機可以像管理堆記憶體一樣對這部分記憶體進行管理,可以通過參數-XX:MaxPermSize指定永久代的上限。而在其他虛擬機實現中並未使用永久代來實現方法區。當方法區無法滿足記憶體分配需要時,便會拋出OutOfMemoryError。
- Java Heap,堆,線程共用,對大部分應用來說,這是JVM種最大的一塊記憶體區域。JVM規範規定:所有的對象實例和數組都要在堆上分配。
堆是記憶體回收的主戰場,因此由稱為Garbage Collected Heap(GC堆),在分代收集策略下。堆可以進一步劃分為新生代和老年代,更細緻的:
- Eden區,對象第一次創建時,從Eden區開闢空間
- Survivor區,當Eden區不足以進行下次記憶體分配時,JVM觸發一次GC,經過GC但未被回收的對象,被轉移到Survivor區。Survivor分為From,To兩部分,多次記憶體回收時未被回收的對象在這兩塊區域中來迴轉移。
- Old區,當經過一定次數的GC後仍未被回收的對象,JVM將其轉移到老年代區
4. JVM Stack,JAVA虛擬機棧,線程私有,其生命周期與對應的線程相同。當每個方法執行時,均會創建一個棧幀(Stack Frame)用於存儲局部變數表,操作數棧,動態鏈接,方法出口等信息。每個方法的執行和完成,便對應著Stack Frame在虛擬機棧中的出棧和入棧的過程。通常意義上粗糙地將JVM記憶體劃分為堆和棧,其中的棧便指的是JVM Stack.
5. Native Method Stack,本地方法棧,與JVM Stack類似,本地方法棧對應的是Native方法的執行管理。
此外,程式運行所需要的記憶體開闢在JVM的記憶體空間中,也可以直接申請系統記憶體(Directive Memory),但是直接申請的系統記憶體不受JVM的垃圾回收管理,其釋放由系統層面控制,因此對於不關註記憶體回收的JAVA程式員來說,容易導致記憶體溢出等問題的發生。