JVM 方法區


  方法區與Java堆一樣,是各個線程共享的內存區域,它用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼等數據。

  使用HotSpot虛擬機的用戶,更願意把方法區稱為“永久代”,本質上兩者並不等價,僅僅是因為HotSpot虛擬機的設計團隊選擇把GC分代收集至方法區,或者說用永久代來實現方法區而已。這樣HotSpot的垃圾收集器可以像管理Java堆一樣管理這部分內存,能省去專門為方法區編寫內存管理代碼的工作。

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

  元空間本質和永久代類似,都是對JVM規范中方法區的實現。不過元空間與永久代之間最大的區別在於:元空間並不在虛擬機中,而是使用本地內存。因此默認情況下元空間的大小僅受本地內存限制。

  即方法區里存放着類的版本、字段、方法、接口和常量池(存儲字面量和符號引用)。

  符號引用包括:1、類的權限定名;2、字段名和屬性;3、方法名和屬性。

  1、類型信息:

    類的完整名稱

    類的直接父類的完整名稱

    類的直接實現接口的有序列表

    類型標志(類類型還是接口類型)

    類的修飾符(public private defautl abstract final static)

  2、類型的常量池

    存放該類型所用到的常量的有序集合,包括直接常量(字符串、整數、浮點數)和對其他類型、字段、方法的符號引用。

  3、字段信息(該類聲明的所有字段)

    字段修飾符(public、peotect、private、default)

    字段的類型

    字段名稱

  4、方法信息

    方法信息中包含類的所有方法。

    方法修飾符

    方法返回類型

    方法名

    方法參數個數、類型、順序等

    方法字節碼

    操作數棧和該方法在棧幀中的局部變量區大小

    異常表

  5、類變量(靜態變量)

  6、指向類加載器的引用

  7、指向Class實例的引用

  8、方法表

  9、運行時常量池(Runtime Constant Pool)

 

總結:

  HotSpot JVM中,永久代中用於存放類和方法的元數據以及常量池。每當一個類初次被加載的時候,它的元數據都會被放到永久代中。

  永久代大小有限制,如果加載的類太多,很可能導致永久代內存溢出,即java.lang.OutOfMemoryError: PermGen。

  Java 8中PermGen被移出HotSpot JVM了:

  1. 由於 PermGen 內存經常會溢出,引發惱人的 java.lang.OutOfMemoryError: PermGen,因此 JVM 的開發者希望這一塊內存可以更靈活地被管理,不要再經常出現這樣的 OOM
  2. 移除 PermGen 可以促進 HotSpot JVM 與 JRockit VM 的融合,因為 JRockit 沒有永久代。

  PermGen最終被移出,方法區移至Metaspace,字符串常量移至Java Heap。

  JDK8把類的元數據放到本地堆內存(native heap)中,這一塊區域就叫Metaspace,中文名叫元空間。

  如果Metaspace的空間占用達到了設定的最大值,那么就會觸發GC來收集死亡對象和類的加載器。

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM