深入探究 JVM | 探秘 Metaspace

Posted 半卷清詞

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入探究 JVM | 探秘 Metaspace相关的知识,希望对你有一定的参考价值。

ava 8 彻底将永久代 (PermGen) 移除出了 HotSpot JVM,将其原有的数据迁移至 Java Heap 或 Metaspace。这一篇文章我们来总结一下Metaspace(元空间)的特性。如有错误,敬请指出,谢谢~

引言:永久代为什么被移出HotSpot JVM了?
在 HotSpot JVM 中,永久代中用于存放类和方法的元数据以及常量池,比如Class和Method。每当一个类初次被加载的时候,它的元数据都会放到永久代中。

永久代是有大小限制的,因此如果加载的类太多,很有可能导致永久代内存溢出,即万恶的 java.lang.OutOfMemoryError: PermGen ,为此我们不得不对虚拟机做调优。

那么,Java 8 中 PermGen 为什么被移出 HotSpot JVM 了?我总结了两个主要原因(详见:JEP 122: Remove the Permanent Generation):

由于 PermGen 内存经常会溢出,引发恼人的 java.lang.OutOfMemoryError: PermGen,因此 JVM 的开发者希望这一块内存可以更灵活地被管理,不要再经常出现这样的 OOM
移除 PermGen 可以促进 HotSpot JVM 与 JRockit VM 的融合,因为 JRockit 没有永久代。
根据上面的各种原因,PermGen 最终被移除,方法区移至 Metaspace,字符串常量移至 Java Heap。

探秘元空间
由于 Metaspace 的资料比较少,这里主要是依据Oracle官方的Java虚拟机规范及Oracle Blog里的几篇文章来总结的。

首先,Metaspace(元空间)是哪一块区域?官方的解释是:

In JDK 8, classes metadata is now stored in the native heap and this space is called Metaspace.

也就是说,JDK 8 开始把类的元数据放到本地堆内存(native heap)中,这一块区域就叫 Metaspace,中文名叫元空间。

优点
使用本地内存有什么好处呢?最直接的表现就是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以后,为了避免增加元数据空间的大小,空闲的类元数据的容量的最大比例,不够就会导致垃圾回收。
监控与调优(待补充)
VisualVM、jstat、jstack 可以监测 Metaspace 的动态,后续将更新这里。

以上是关于深入探究 JVM | 探秘 Metaspace的主要内容,如果未能解决你的问题,请参考以下文章

深入理解JVM:HotSpot虚拟机对象探秘

jvm,深入理解java虚拟机,HotSpot虚拟机对象探秘

jvm,深入理解java虚拟机,HotSpot虚拟机对象探秘

jvm,深入理解java虚拟机,HotSpot虚拟机对象探秘

深入探究JVM之垃圾回收器

深入探究jvm之类装载器