深刻探究 JVM | 探祕 Metaspace

Java 8 完全將永久代 (PermGen) 移除出了 HotSpot JVM,將其原有的數據遷移至 Java Heap 或 Metaspace。這一篇文章咱們來總結一下Metaspace(元空間)的特性。若有錯誤,敬請指出,謝謝~html

引言:永久代爲何被移出HotSpot JVM了?

在 HotSpot JVM 中,永久代中用於存放類和方法的元數據以及常量池,好比ClassMethod。每當一個類初次被加載的時候,它的元數據都會放到永久代中。java

永久代是有大小限制的,所以若是加載的類太多,頗有可能致使永久代內存溢出,即萬惡的 java.lang.OutOfMemoryError: PermGen ,爲此咱們不得不對虛擬機作調優。oracle

那麼,Java 8 中 PermGen 爲何被移出 HotSpot JVM 了?我總結了兩個主要緣由(詳見:JEP 122: Remove the Permanent Generation):this

  1. 因爲 PermGen 內存常常會溢出,引起惱人的 java.lang.OutOfMemoryError: PermGen,所以 JVM 的開發者但願這一塊內存能夠更靈活地被管理,不要再常常出現這樣的 OOM
  2. 移除 PermGen 能夠促進 HotSpot JVM 與 JRockit VM 的融合,由於 JRockit 沒有永久代。

根據上面的各類緣由,PermGen 最終被移除,方法區移至 Metaspace,字符串常量移至 Java Heapspa

探祕元空間

因爲 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的大小。對象

除此以外,它還有如下優勢:

  • Take advantage of Java Language Specification property : Classes and associated metadata lifetimes match class loader’s
  • Linear allocation only
  • No individual reclamation (except for RedefineClasses and class loading failure)
  • No GC scan or compaction
  • No relocation for metaspace objects

GC

若是Metaspace的空間佔用達到了設定的最大值,那麼就會觸發GC來收集死亡對象和類的加載器。根據JDK 8的特性,G1和CMS都會很好地收集Metaspace區(通常都伴隨着Full GC)。

爲了減小垃圾回收的頻率及時間,控制吞吐量,對Metaspace進行適當的監控和調優是很是有必要的。若是在Metaspace區發生了頻繁的Full GC,那麼可能表示存在內存泄露或Metaspace區的空間過小了。

新增的 JVM 參數

  • -XX:MetaspaceSize 是分配給類元數據空間(以字節計)的初始大小(Oracle邏輯存儲上的初始高水位,the initial high-water-mark ),此值爲估計值。MetaspaceSize的值設置的過大會延長垃圾回收時間。垃圾回收事後,引發下一次垃圾回收的類元數據空間的大小可能會變大。
  • -XX:MaxMetaspaceSize 是分配給類元數據空間的最大值,超過此值就會觸發Full GC,此值默認沒有限制,但應取決於系統內存的大小。JVM會動態地改變此值。
  • -XX:MinMetaspaceFreeRatio 表示一次GC之後,爲了不增長元數據空間的大小,空閒的類元數據的容量的最小比例,不夠就會致使垃圾回收。
  • -XX:MaxMetaspaceFreeRatio 表示一次GC之後,爲了不增長元數據空間的大小,空閒的類元數據的容量的最大比例,不夠就會致使垃圾回收。

監控與調優(待補充)

VisualVMjstatjstack 能夠監測 Metaspace 的動態,後續將更新這裏。


參考資料

相關文章
相關標籤/搜索