天天看點

深入JVM(Java虛拟機)(一)Java虛拟機記憶體區域劃分

   本文為部落客參閱自《深入了解Java虛拟機:JVM進階特性與最佳實踐(第2版)》,書中的全部講解均以《Java虛拟機規範(Java SE 7)》為依據

深入JVM(Java虛拟機)(一)Java虛拟機記憶體區域劃分

圖一中為JVM規範中對java虛拟機記憶體區域的劃分及定義,為單線程時的粗略劃分

深入JVM(Java虛拟機)(一)Java虛拟機記憶體區域劃分

圖二,中所繪為JVM在多線程情況下運作時的各區域間關系,

1、Java堆

在Java虛拟機中,堆是可供各個線程共享的運作時記憶體區域,也是供所有類執行個體和數組對象配置設定記憶體的區域。這塊區域随着虛拟機的啟動而建立,它的唯一使命就是存放對象執行個體,這塊區域也是GC主要關注的地方。可以細分為新生代、老年代和永久代,新生代裡面又可以分為Eden Space、From Survivor Space和To Survivor Space。

Java堆可以是固定的大小也可以是按照需求動态擴充的,而且不需要保證是連續的。

存放内容:所有的對象和數組。

2、方法區

方法區是一個線程共享的區域,它用于存儲已被虛拟機加載的類資訊、常量、靜态變量。方法區是堆的邏輯組成部分,Hotspot用永久代實作了方法區。

方法區還包含運作時常量池,用于存放編譯時生成的各種字面量和符号引用,但是不要求常量一定是在編譯時期産生的,運作期間也可以将新的常量放入池中,比如String的intern()方法便是利用了這一特性。

存放内容:類的結構資訊,如類的字段、方法、接口、構造函數,還有運作時常量池等。

3、運作時常量池

運作時常量池是方法區的一部分,用于存放在編譯期産生的字面量和符号引用,這部分内容将在類加載後進入方法區的常量池中存放,也可以在運作期将新的常量放到池中,例如String類中的intern()方法。

4、程式計數器

這塊區域是每個線程獨立擁有的,也就是線程私有的,我們可以把它看作是目前線程所執行的位元組碼的行号訓示器。

這塊區域時虛拟機規範裡面唯一一個沒有規定任何OutOfMemoryError情況的區域。

存放内容:如果線程執行的是一個Java方法,那麼寄存器裡面記錄的就是正在執行的虛拟機位元組碼指令的位址,如果線程執行的是一個native方法,那麼寄存器記錄的值為undefined。

5、虛拟機棧

虛拟機棧也是線程私有的記憶體區域。每個方法在執行的時候都會建立一個棧幀用于存儲局部變量表、操作數棧、方法出口等資訊,每一個方法從調用到執行完成就是一個棧幀入棧和出棧的過程。

局部變量表存放了編譯時期可知的各種基本資料類型、對象引用和指向了一條位元組碼指令的位址。

存放内容:局部變量表、操作數棧、方法出口等資訊。

6、本地方法棧

和虛拟機棧類似,本地方法棧為虛拟機使用到的Native方法服務,有的虛拟機中将本地方法棧與虛拟機棧合二為一。

直接記憶體

直接記憶體(Direct Memory)并不是虛拟機運作時資料區的一部分,也不是Java虛拟機規範中定義的記憶體區域,但在Java1.4中新加入的NIO相關類中,會使用Native函數庫配置設定堆外記憶體,并使用堆中的DirectByteBuffer對象操作所申請的堆外記憶體,是以本文中将這部分拿出來,作為對詞彙的解釋,以便讀者在被提到這部分區域時,能有所了解。