JVM內存結構

根據 JVM 規範,JVM 內存共分爲虛擬機棧、堆、方法區、程序計數器、本地方法棧五個部分。

1、虛擬機棧:

每個線程有一個私有的棧,隨着線程的創建而創建。棧裏面存着的是一種叫“棧幀”的東西,每個方法會創建一個棧幀,棧幀中存放了局部變量表(基本數據類型和對象引用)、操作數棧、方法出口等信息。棧的大小可以固定也可以動態擴展。當棧調用深度大於JVM所允許的範圍,會拋出StackOverflowError的錯誤,不過這個深度範圍不是一個恆定的值。

虛擬機棧除了上述錯誤外,還有另一種錯誤,那就是當申請不到空間時,會拋出 OutOfMemoryError。

2. 本地方法棧

與虛擬機棧類似,區別是虛擬機棧執行java方法,本地方法站執行native方法。在虛擬機規範中對本地方法棧中方法使用的語言、使用方法與數據結構沒有強制規定,因此虛擬機可以自由實現它。本地方法棧也可以拋出StackOverflowError和OutOfMemoryError。

 

3. PC 寄存器

也叫程序計數器。可以看成是當前線程所執行的字節碼的行號指示器。

在任何一個確定的時刻,一個處理器(對於多內核來說是一個內核)都只會執行一條線程中的指令。因此,爲了線程切換後能恢復到正確的執行位置,每條線程都需要一個獨立的程序計數器,我們稱這類內存區域爲“線程私有”內存。

倘若當前線程執行的是 JAVA 的方法,則該寄存器中保存當前執行指令的地址;倘若執行的是native 方法,則PC寄存器中爲空。

 

4. 堆內存

是 JVM 所有線程共享的部分,在虛擬機啓動的時候就已經創建。所有的對象和數組都在堆上進行分配。這部分空間可通過 GC 進行回收。當申請不到空間時會拋出 OutOfMemoryError。

 

5. 方法區

也是所有線程共享。主要用於存儲類的信息、常量池、靜態變量、及時編譯器編譯後的代碼等數據。方法區邏輯上屬於堆的一部分,但是爲了與堆進行區分,通常又叫“非堆”。 關於方法區內存溢出的問題會在下文中詳細探討。

 

6 PermGen(永久代)

絕大部分 Java 程序員應該都見過 "java.lang.OutOfMemoryError: PermGen space "這個異常。這裏的 “PermGen space”其實指的就是方法區。不過方法區和“PermGen space”又有着本質的區別。前者是 JVM 的規範,而後者則是 JVM 規範的一種實現,並且只有 HotSpot 纔有 “PermGen space”,而對於其他類型的虛擬機,如 JRockit(Oracle)、J9(IBM) 並沒有“PermGen space”。由於方法區主要存儲類的相關信息,所以對於動態生成類的情況比較容易出現永久代的內存溢出。最典型的場景就是,在 jsp 頁面比較多的情況,容易出現永久代內存溢出。

 

7. Metaspace(元空間)

 

其實,移除永久代的工作從JDK1.7就開始了。JDK1.7中,存儲在永久代的部分數據就已經轉移到了Java Heap或者是 Native Heap。但永久代仍存在於JDK1.7中,並沒完全移除,譬如符號引用(Symbols)轉移到了native heap;字面量(interned strings)轉移到了java heap;類的靜態變量(class statics)轉移到了java heap。


元空間的本質和永久代類似,都是對JVM規範中方法區的實現。不過元空間與永久代之間最大的區別在於:元空間並不在虛擬機中,而是使用本地內存。因此,默認情況下,元空間的大小僅受本地內存限制,但可以通過以下參數來指定元空間的大小:
-XX:MetaspaceSize,初始空間大小,達到該值就會觸發垃圾收集進行類型卸載,同時GC會對該值進行調整:如果釋放了大量的空間,就適當降低該值;如果釋放了很少的空間,那麼在不超過MaxMetaspaceSize時,適當提高該值。

-XX:MaxMetaspaceSize,最大空間,默認是沒有限制的。

除了上面兩個指定大小的選項以外,還有兩個與 GC 相關的屬性:

-XX:MinMetaspaceFreeRatio,在GC之後,最小的Metaspace剩餘空間容量的百分比,減少爲分配空間所導致的垃圾收集

-XX:MaxMetaspaceFreeRatio,在GC之後,最大的Metaspace剩餘空間容量的百分比,減少爲釋放空間所導致的垃圾收集

 

8. 爲什麼從永久代切換到元空間?

1)字符串存在永久代中,容易出現性能問題和內存溢出。

2)類及方法的信息等比較難確定其大小,因此對於永久代的大小指定比較困難,太小容易出現永久代溢出,太大則容易導致老年代溢出。

3)永久代會爲 GC 帶來不必要的複雜度,並且回收效率偏低。

 

9.jvm調優

                                               這張圖能很清晰的說明JVM內存結構的佈局和相應的控制參數

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