序
本文主要講述一下jvm的PermGen與Metaspace
java memory結構
分代概念
對於垃圾收集演算法來說,分代回收是高階演算法之一。物件按照生成時間進行分代,剛剛生成不久的年輕物件劃為新生代(Young gen-eration),而存活了較長時間的物件劃為老生代(Old generation)。根據具體實現方式的不同,可能還會劃分更多的代。比如有的把永久代也算做一個代。
memory劃分
java memory主要分heap memory 和 non-heap memory,其計算公式如下:
Max memory = [-Xmx] + [-XX:MaxPermSize] + number_of_threads * [-Xss]
複製程式碼
- heap結構
按分代,分young-eden,young-survivor,old 用-Xmn,-Xms,-Xmx來指定
- non-heap結構
包括metaspace,thread stacks,compiled native code,memory allocated by native code
-XX:PermSize或-XX:MetaspceSize,-Xss或-XX:ThreadStackSize
PermGen與Metaspace
字串常量池的變化
- 在java7的時候將字串常量池則移到java heap
所有的被intern的String被儲存在PermGen區.PermGen區使用-XX:MaxPermSize=N來設定最大大小,但是由於應用程式string.intern通常是不可預測和不可控的,因此不好設定這個大小。設定不好的話,常常會引起
java.lang.OutOfMemoryError: PermGen space
複製程式碼
- java7,8的字串常量池在堆中實現 字串常量池被限制在整個應用的堆記憶體中,在執行時呼叫String.intern()增加字串常量不會使永久代OOM了。
方法區的變化
- java8的時候去除PermGen,將其中的方法區移到non-heap中的Metaspace
move name and fields of the class, methods of a class with the bytecode of the methods, constant pool, JIT optimizations etc to metaspace
- Metaspace屬於non-heap
Metaspace與PermGen之間最大的區別在於:Metaspace並不在虛擬機器中,而是使用本地記憶體。
如果沒有使用-XX:MaxMetaspaceSize來設定類的後設資料的大小,其最大可利用空間是整個系統記憶體的可用空間。JVM也可以增加本地記憶體空間來滿足類後設資料資訊的儲存。 但是如果沒有設定最大值,則可能存在bug導致Metaspace的空間在不停的擴充套件,會導致機器的記憶體不足;進而可能出現swap記憶體被耗盡;最終導致程式直接被系統直接kill掉。
- OOM異常 如果類後設資料的空間佔用達到MaxMetaspaceSize設定的值,將會觸發物件和類載入器的垃圾回收。
java.lang.OutOfMemoryError: Metaspace space
複製程式碼
JVM從Metaspace在捕獲一個一個記憶體分配失敗後丟擲。
Metaspace相關引數
- -XX:MetaspaceSize,初始空間大小,達到該值就會觸發垃圾收集進行型別解除安裝,同時GC會對該值進行調整:如果釋放了大量的空間,就適當降低該值;如果釋放了很少的空間,那麼在不超過MaxMetaspaceSize時,適當提高該值。
- -XX:MaxMetaspaceSize,最大空間,預設是沒有限制的。
- -XX:MinMetaspaceFreeRatio,在GC之後,最小的Metaspace剩餘空間容量的百分比,減少為分配空間所導致的垃圾收集
- -XX:MaxMetaspaceFreeRatio,在GC之後,最大的Metaspace剩餘空間容量的百分比,減少為釋放空間所導致的垃圾收集
小結
將常量池從PermGen剝離到heap中,將後設資料從PermGen剝離到後設資料區,去除PermGen的好處如下:
- 將字串常量池從PermGen分離出來,與類後設資料分開,提升類後設資料的獨立性
- 將後設資料從PermGen剝離出來到Metaspace,可以提升對後設資料的管理同時提升GC效率。
在PermGen中後設資料可能會隨著每一次Full GC發生而進行移動。HotSpot虛擬機器的每種型別的垃圾回收器都需要特殊處理PermGen中的後設資料,分離出來以後可以簡化Full GC以及對以後的併發隔離類後設資料等方面進行優化。
- 為後續將HotSpot與JRockit合二為一做準備。
PermGen是HotSpot的實現特有的,JRockit並沒有PermGen一說