Java 8徹底將永久代移除出了HotSpot JVM,將其原有的數(shù)據(jù)遷移至Java Heap或Metaspace。這一篇文章我們來總結(jié)一下Metaspace(元空間)的特性。如有錯(cuò)誤,敬請指出,謝謝~
詳見:JEP 122: Remove the Permanent Generation
原因主要有兩個(gè):
This is part of the JRockit and Hotspot convergence effort. JRockit customers do not need to configure the permanent generation (since JRockit does not have a permanent generation) and are accustomed to not configuring the permanent generation.
根據(jù)上面的各種原因,永久代最終被移除,方法區(qū)移至Metaspace,字符串常量移至Java Heap。
由于Metaspace的資料比較少,這里主要是依據(jù)Oracle官方的Java虛擬機(jī)規(guī)范及Oracle Blog里的幾篇文章來總結(jié)的。
首先,Metaspace(元空間)是哪一塊區(qū)域?官方的解釋是:
In JDK 8, classes metadata is now stored in the native heap and this space is called Metaspace.
也就是說,JDK 8開始把類的元數(shù)據(jù)放到本地化的堆內(nèi)存(native heap)中,這一塊區(qū)域就叫Metaspace,中文名叫元空間。
使用本地化的內(nèi)存有什么好處呢?最直接的表現(xiàn)就是java.lang.OutOfMemoryError: PermGen 空間問題將不復(fù)存在,因?yàn)槟J(rèn)的類的元數(shù)據(jù)分配只受本地內(nèi)存大小的限制,也就是說本地內(nèi)存剩余多少,理論上Metaspace就可以有多大(貌似容量還與操作系統(tǒng)的虛擬內(nèi)存有關(guān)?這里不太清楚),這解決了空間不足的問題。不過,讓Metaspace變得無限大顯然是不現(xiàn)實(shí)的,因此我們也要限制Metaspace的大?。菏褂?strong>-XX:MaxMetaspaceSize參數(shù)來指定Metaspace區(qū)域的大小。JVM默認(rèn)在運(yùn)行時(shí)根據(jù)需要?jiǎng)討B(tài)地設(shè)置MaxMetaspaceSize的大小。
除此之外,它還有以下優(yōu)點(diǎn)(沒有完全理解,先貼出來吧,來自StackOverflow):
如果Metaspace的空間占用達(dá)到了設(shè)定的最大值,那么就會(huì)觸發(fā)GC來收集死亡對象和類的加載器。根據(jù)JDK 8的特性,G1和CMS都會(huì)很好地收集Metaspace區(qū)(一般都伴隨著Full GC)。
為了減少垃圾回收的頻率及時(shí)間,控制吞吐量,對Metaspace進(jìn)行適當(dāng)?shù)谋O(jiān)控和調(diào)優(yōu)是非常有必要的。如果在Metaspace區(qū)發(fā)生了頻繁的Full GC,那么可能表示存在內(nèi)存泄露或Metaspace區(qū)的空間太小了。
VisualVM,jstat,jstack可以監(jiān)測元空間的動(dòng)態(tài),后續(xù)將更新這里。
[1]《The Java Virtual Machine Specification, Java SE 8 Edition》, Oracle.
[2]What is the use of Metaspace in Java 8? - StackOverflow
[3]About G1 Garbage Collector, Permanent Generation and Metaspace
[4]JEP 122: Remove the Permanent Generation
[5]PermGen elimination in JDK 8 - StackOverflow
聯(lián)系客服