4年前 (2020-09-10)  爪哇岛 |   抢沙发  3895 
文章评分 2 次,平均分 4.0

Oracle JDK或OpenJDK使用元空间存储其类元数据。它可以为java vm进程的非Java堆内存占用贡献很大一部分。

我们解释它是什么,为什么我们需要它。一个简短,快速,希望容易阅读,而不是深入到虚拟机内部。每个人都能消化。

Note: JDK version dependencies: Metaspace implementation changed quite a bit since JDK 8. In these articles, when not explicitly stated differently, we talk about JDK 11.

Metaspace是VM用来存储类元数据的内存。

java类的元数据基本上都是一个java类运行时所需的java类的表示。这包括但不限于JVM类文件格式的数据的运行时表示。

示例:

  • “Class”结构——java类运行时状态的VM内部表示。这包括vtable和itable。
  • Method metadata-类文件中Method_info的运行时等效项,包含字节码、异常表、常量等内容。
  • 常量池
  • 注解
  • 在运行时收集的方法计数器作为JIT决策的基础
  • 等等

Note: We will examine all this in more detail in Part 4 of this series.

Another good introduction into class metadata in hotspot is Andrew Dinn’s talk at FOSDEM 18.

尽管java.lang.Class是一个生活在java堆中的java对象,类元数据本身不是java对象,也不存在于java堆中。它们位于Java堆之外的本机内存区域中。这个区域被称为元空间。

元空间metaspace在什么时候分配?

元空间的分配与类加载相耦合。

当一个类被加载并且它在JVM中的运行时表示正在准备时,它的类加载器会分配元空间来存储类的元数据。

Java元空间metaspace到底是什么?

元空间metaspace内存何时释放?

为类分配的元空间归其类装入器1所有。它只在类装入器本身被卸载时释放,而不是在卸载之前。

反过来,只有当这个加载程序加载的所有类不再有活动实例,并且没有对这些类及其类装入器的引用,并且GC确实运行了(参见:jls12.7)。类和接口的卸载)。

Java元空间metaspace到底是什么?

释放Metaspace并不一定意味着内存返回到操作系统

这些内存的全部或一部分可以保留在JVM中;它可以被重用以供将来的类加载,但目前它在JVM进程中仍然没有使用。

这个部分有多大,主要取决于元空间的碎片化程度,以及元空间的使用和空闲部分有多紧密。另外,Metaspace(压缩类空间)的一部分根本不会返回给操作系统。

Note: An in-depth look at the release logic follows in Part 2.

Note: Concern about Metaspace footprint is a good reason to upgrade to JDK 11 - it got a number of significant improvements in this area, reducing fragmentation and memory waste.

有两个参数可以限制元空间大小:

  • -XX:MaxMetaspaceSize确定允许元空间增长的最大提交大小。默认情况下是无限的。
  • -XX:CompressedClassSpaceSize确定元空间的一个重要部分压缩类空间的虚拟大小。它的默认值是1G(注意:保留空间,未提交)。

具体可以参考这篇文章:https://javakk.com/384.html

元空间metaspace与gc垃圾回收

只有在GC卸载程序运行空间加载程序时才释放metaloader。因此,在某种程度上,运行GC来清理过时的类元数据是有意义的,即使在常规Java堆中GC没有获得太多好处时也是如此。在两种情况下会触发元空间诱导的GC:

  • 当分配元空间时:VM拥有一个阈值,超过这个阈值时,如果不首先尝试收集旧类装入器(从而通过触发GC重用它们的元空间),它就不会增长元空间。这一点就是元空间GC阈值。它可以防止元空间在不释放过时元数据的情况下增长。这个阈值会上下移动,大致遵循提交的元空间总和的一定幅度。
  • 当遇到元空间OOM时(无论是在提交的内存总量达到MaxMetaspaceSize上限时,还是在压缩类空间用完时),GC会尝试纠正这种情况。如果它真的卸载了类加载器,这很好,否则我们可能会陷入一个糟糕的GC循环,即使我们有足够的Java堆。
 

除特别注明外,本站所有文章均为老K的Java博客原创,转载请注明出处来自https://javakk.com/391.html

关于

发表评论

表情 格式

暂无评论

登录

忘记密码 ?

切换登录

注册