1、移除方法區
JDK 1.7及之前方法區存放的數據有類信息(類名,修飾符,字段描述,方法描述等),常量,靜態變量,即時編譯后的class文件。
方法區中還包含有常量池:常量池中主要有字面量和符號引用
字面量:文本字符串,聲明為final的常量值;
符號引用:包括了三種常量,分別是:類和接口的全限定名,字段的名稱和描述符,方法的名稱和修飾符。
為什么移除方法區?
1、它在啟動時固定大小,很難進行調優,並且FullGC時會移動類元信息
2、類及方法的信息等比較難確定大小,因此對永久代的大小指定比較困難
3、在某些場景下,如果動態加載類過多,容易造成Perm區的OOM。
4、字符串存在方法區中,容易出現性能問題和內存溢出
5、永久代(在GC時用永久代實現方法區)GC垃圾回收效率偏低(回收目標主要是常量池和類型的卸載)
6、永久代的垃圾收集和老年代捆綁在一起的,因此無論誰滿了,都會觸發永久代和老年代的垃圾收集
2、MetaSpace元空間 取而代之
JDK 1.8將方法區中的字符串常量移至堆內存,其他內容如類信息、靜態變量、其他常量(如整形常量),即時編譯后的class文件等都移動到元空間內。
元空間(MetaSpace)不在堆內存上,而是直接占用的本地內存。因此元空間的大小僅受本地內存限制。也可通過參數來設定元空間的大小
-XX:MetaSpaceSize 初始元空間大小,達到該值就會觸發垃圾收集器進行類型卸載,同時GC會對該值進行調整:如果釋放了大量的空間,就適當降低
該值;如果釋放了很少的空間,那么在不超過MaxMetaSpaceSize時,適當提高該值。
-XX:MaxMetaSpaceSize 最大元空間大小,默認沒有限制
元空間的特點:
1、每個加載器有專門的存儲空間。
2、不會單獨回收某個類。
3、元空間里的對象的位置是固定的。
4、如果發現某個加載器不再存活了,會把相關的空間整個回收。