1. 程式人生 > >java 8中撤銷永久代,引入元空間

java 8中撤銷永久代,引入元空間

問題 java 8 性能問題 ror 虛擬機 rac 錯誤 元空間 規範

撤銷永久代,引入元空間:

  在 JDK 1.8 中,HotSpot 已經沒有 “PermGen space”這個空間了,取而代之是一個叫做 Metaspace(元空間) 的東西。

  Java7中已經將字符串常量池從永久代移除,在Java 堆(Heap)中開辟了一塊區域存放字符串常量池。而在Java8中,已經徹底沒有了永久代,將方法區直接放在一個與堆不相連的本地內存區域,這個區域被叫做元空間。

  移除永久代後,不會遇到永久代存在的內存溢出錯誤,也不會出現泄漏的數據移到交換區這樣的事情。最終用戶可以為元空間設置一個可用空間最大值,如果不進行設置,JVM會自動根據類的元數據大小動態增加元空間的容量。

  這項改動是很有必要的,因為對永久代進行調優是很困難的。永久代中的元數據可能會隨著每一次Full GC發生而進行移動。

PermGen(永久代)

  “PermGen space”是指永久代。方法區和“PermGen space”有著本質的區別。前者是 JVM 的規範,而後者則是 JVM 規範的一種實現,並且只有 HotSpot 才有 “PermGen space”,而對於其他類型的虛擬機,如 JRockit(Oracle)、J9(IBM) 並沒有“PermGen space”。由於方法區主要存儲類的相關信息,所以對於動態生成類的情況比較容易出現永久代的內存溢出。最典型的場景就是,在 jsp 頁面比較多的情況,容易出現永久代內存溢出。

  永久代的垃圾回收和老年代的垃圾回收是綁定的,一旦其中一個區域被占滿,這兩個區都要進行垃圾回收。

Metaspace(元空間)

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

  元空間的本質和永久代類似,都是對JVM規範中方法區的實現。不過元空間與永久代之間最大的區別在於:元空間並不在虛擬機中,而是使用本地內存

。因此,默認情況下,元空間的大小僅受本地內存限制,但可以通過以下參數來指定元空間的大小

永久代為什麽被移出HotSpot JVM了?

  1、由於Permanent Generation內存經常不夠用或發生內存泄露,引發惱人的java.lang.OutOfMemoryError: PermGen (在Java Web開發中非常常見)。

  2、移除Permanent Generation可以促進HotSpot JVM與JRockit VM的融合,因為JRockit沒有永久代。

  3、對永久代進行調優是很困難的。

為什麽要引入元空間:

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

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

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

  4、Oracle 可能會將HotSpot 與 JRockit 合二為一。

java 8中撤銷永久代,引入元空間