Java 8 完全將永久代 (PermGen) 移除出了 HotSpot JVM,將其原有的數據遷移至 Java Heap 或 Metaspace。這一篇文章咱們來總結一下Metaspace(元空間)的特性。若有錯誤,敬請指出,謝謝~html
在 HotSpot JVM 中,永久代中用於存放類和方法的元數據以及常量池,好比Class
和Method
。每當一個類初次被加載的時候,它的元數據都會放到永久代中。java
永久代是有大小限制的,所以若是加載的類太多,頗有可能致使永久代內存溢出,即萬惡的 java.lang.OutOfMemoryError: PermGen ,爲此咱們不得不對虛擬機作調優。oracle
那麼,Java 8 中 PermGen 爲何被移出 HotSpot JVM 了?我總結了兩個主要緣由(詳見:JEP 122: Remove the Permanent Generation):this
根據上面的各類緣由,PermGen 最終被移除,方法區移至 Metaspace,字符串常量移至 Java Heap。spa
因爲 Metaspace 的資料比較少,這裏主要是依據Oracle官方的Java虛擬機規範及Oracle Blog裏的幾篇文章來總結的。操作系統
首先,Metaspace(元空間)是哪一塊區域?官方的解釋是:.net
In JDK 8, classes metadata is now stored in the native heap and this space is called Metaspace.code
也就是說,JDK 8 開始把類的元數據放到本地堆內存(native heap)中,這一塊區域就叫 Metaspace,中文名叫元空間。htm
使用本地內存有什麼好處呢?最直接的表現就是OOM問題將不復存在,由於默認的類的元數據分配只受本地內存大小的限制,也就是說本地內存剩餘多少,理論上Metaspace就能夠有多大(貌似容量還與操做系統的虛擬內存有關?這裏不太清楚),這解決了空間不足的問題。不過,讓 Metaspace 變得無限大顯然是不現實的,所以咱們也要限制 Metaspace 的大小:使用 -XX:MaxMetaspaceSize 參數來指定 Metaspace 區域的大小。JVM 默認在運行時根據須要動態地設置 MaxMetaspaceSize的大小。對象
除此以外,它還有如下優勢:
若是Metaspace的空間佔用達到了設定的最大值,那麼就會觸發GC來收集死亡對象和類的加載器。根據JDK 8的特性,G1和CMS都會很好地收集Metaspace區(通常都伴隨着Full GC)。
爲了減小垃圾回收的頻率及時間,控制吞吐量,對Metaspace進行適當的監控和調優是很是有必要的。若是在Metaspace區發生了頻繁的Full GC,那麼可能表示存在內存泄露或Metaspace區的空間過小了。
VisualVM
、jstat
、jstack
能夠監測 Metaspace 的動態,後續將更新這裏。