4年前 (2020-09-15)  爪哇岛 |   抢沙发  3745 
文章评分 0 次,平均分 0.0

MaxMetaspaceSize和CompressedClassSpaceSize是控制元空间大小的旋钮

现在,这些参数可能有点混乱。首先,它们有两种,它们有着微妙的不同含义,它们相互影响。

所以让我们仔细看看。我们将详细解释这些参数是如何工作的。然后,我们将分析单个类平均需要多少元空间。最后,我们将尝试导出一些粗略的经验法则,并检查默认行为是什么。

推荐阅读:https://javakk.com/405.html

这里再明确两个概念:

  • MaxMetaspaceSize:这是对提交的元空间最大值的“软”限制。它包括非类空间和类空间。从这个意义上说,它是“软”的,因为除了希望有一个限制之外,没有紧迫的技术原因。它是完全可选的,实际上在默认情况下是关闭的。
  • CompressedClassSpaceSize:这是一个硬限制,定义压缩类空间的虚拟大小。“很难”,因为我们需要在VM启动时修复它,而且永远无法更改它。如果我们省略它,它默认为1G。

此图说明了这些限制是如何工作的:

调整元空间metaspace大小

红色部分是Metaspace的提交部分的总和,包括非类空间节点和一个巨大的类空间节点。此总和受-XX:MaxMetaspaceSize限制。尝试提交超过-XX:MaxMetaspaceSize的内存将导致OutOfMemoryError("Metaspace")

-XX:MaxMetaspaceSize的目的当然很简单:对提交的Metaspace大小有一个最大限制。它永远不会超过这一点。

另一方面,确定了一个保留空间的大小。它包括已提交部分和(蓝色)尚未提交部分。如果该节点已满,我们将得到一个OutOfMemoryError("Compressed Class Space")。

注意:如第3部分所述,我们使用压缩类指针开关。默认情况下,它是打开的,但如果关闭,则不会有压缩的类空间,-XX:CompressedClassSpaceSize将被忽略,并且元空间仅受-XX:MaxMetaspaceSize的限制。整个事情变得简单得多。

那么,这是什么意思?

加载Java类时,它需要非类空间和类空间中的内存。由于后者始终是有限的,因此即使-XX:MaxMetaspaceSize不受限制,我们也会有效地为元空间的增长设置一个上限。

这个cap命中的位置取决于加载的类的大小(详见下文),这决定了非类空间和类空间使用率之间的比率。

例如,假设(合理)比率为1:5类:非类空间每个calss的大小。

这意味着对于默认设置-XX:CompressedClassSpaceSize为1G,我们的上限是~6G:将1G默认大小的压缩类空间填充到边缘将导致分配~5G的非类空间。

一个类需要多少元空间?

对于每个加载的类,将从类和非类空间的类元数据中分配空间。现在去哪?

调整元空间metaspace大小

进入calss类空间

calss空间采用固定尺寸的Klass结构。

接下来是两个可变大小的结构,vtable和itable。前者的大小随方法的数量而增加,后者的大小随从已实现接口继承的接口方法的数量而增加。

接下来是一个映射,它描述对象引用成员在Java类中的位置,即非静态Oopmap。这种结构的尺寸也是可变的,但通常非常小。

vtable和itable通常都很小,但是对于奇怪的大型类,它们可以增长到巨大的比例。一个包含30000个方法的类的vtable的大小将是240k,当从一个包含30000个方法的接口派生时也是一个itable。但这些都是测试用例,除了自动代码生成之外,我们在野外找不到这样的类。

进入非calss空间

在非类空间中有很多东西,其中最大的贡献者是:

  • 常量池,大小可变。
  • 任何一个类方法的元数据:ConstMethod结构,包含大量相关的、大小可变的嵌入式结构,如方法字节码、局部变量表、异常表、参数信息、签名等。
  • 用于控制JIT的运行时方法数据
  • 注释

注意:存储在Metaspace中的结构都是从MetaspaceObj派生的,所以下面的类型树将给您一个很好的印象,什么是在Metaspace中。

类与非类空间的大小比

让我们看看对于典型应用程序,类空间和非类空间的比率是多少。

这里有一个WildFly1服务器,独立的,16.0.0,运行在sapmache11上。没有加载应用程序,只有启动后的裸机服务器。我们检查我们需要多少元空间,以及每个类平均需要多少空间。我们用jcmd测量虚拟机元空间.

loader #classes non-class space (avg per class) class space (/avg per class) ratio non-class/class
all 11503 60381k (5.25k) 9957k (.86k) 6.0 : 1
bootstrap 2819 16720k (5.93k) 1768k (0.62k) 9.5 : 1
app 185 1320k (7.13k) 136k (0.74k) 9.7 : 1
anonymous 869 1013k (1.16k) 475k (0.55k) 2.1 : 1

这说明了什么?

对于标准类(假设bootstrap和app loader加载的类被视为标准类),平均每个类的非类空间约为5-7k,类空间为600-900字节。

匿名(lambda)类要小得多,这并不奇怪,但有趣的是,类和非类空间的使用比例也被扭曲了:相对于非类空间,我们需要更多的类空间。这并不奇怪,因为Lambda类很小,但是Klass结构的开销不能缩小到sizeof(Klass)结构本身之下。所以,我们来到1k的非类空间,.5k类空间。

注意,在我们的例子中,匿名类并不重要。为了使它们的影响显著,必须分配更多的匿名类。

元空间metaspace默认大小

如果不对元空间设置任何限制,它能容纳多少个类?

默认情况下,MaxMetaspaceSize是无限的,而CompressedClassSpaceSize的大小是1G。这意味着我们遇到的唯一限制是CompressedClassSpaceSize。

使用上面的示例数字(~5-7k非类空间,600-900字节的类空间),在理想情况下(如果没有碎片化,没有浪费),在压缩类空间中遇到OutOfMemoryError之前,我们可以容纳大约1..1,5百万个类。这是一个非常多的元数据,而且肯定有点过头了。

但是,CompressedClassSpaceSize只是保留空间,而不是提交的。所以它“没有那么大的伤害”—我们实际上只使用类空间的提交部分。

元空间metaspace限制

免责声明:不要盲目使用你在网上发现的任何规则,尤其是不在生产中!

请注意,这里实际上没有那么多选择。当然可以限制元空间的增长。但是如果你这样做了,并且你的程序需要比你允许的更多的空间来存放类元数据,它只会因为OOM而失败。在重写程序以加载较少的类之前,您无能为力。

与Java堆比较:您可以在一定的限制内增加或减少Java堆,而不会影响程序的主要功能—这里有某种灵活性,这是元空间所没有的。

那么你为什么要限制元空间呢?

  • 作为一个警告系统,一个“健全的封套”,知道什么时候元空间的消耗超过了它应该有人看看。
  • 有时可能需要限制虚拟内存大小(又称ps“size”列)。虽然常驻集大小(resident set size,RSS)通常是真正有趣的统计值,但虚拟内存大小可能会导致VM进程达到配额。

注意:JDK版本依赖性:jdk8中的元空间比jdk11或更高版本更容易受到碎片的影响。请记住这一点,如果您运行的是较旧的jdk,那么可以增加一个健康的裕度。

如果您想限制元空间大小,使其具有“健全的封套”,并且不关心虚拟进程的大小,那么最好只设置MaxMetaspaceSize并保持CompressedClassSpaceSize不变。如果单独使用,CompressedClassSpaceSize将默认为MaxMetaspaceSize的80%—这可能会有点过度补偿,但请记住,这只是保留空间,而不是提交。

除了MaxMetaspaceSize之外,减少CompressedClassSpaceSize的唯一原因是减少VM进程的虚拟内存大小。但请记住,如果将CompressedClassSpaceSize设置得太低,则可能会在用完MaxMetaspaceSize之前填充压缩的类空间。也就是说,在大多数情况下,1:2(CompressedClassSpaceSize=MaxMetaspaceSize/2)的比率应该是安全的。

那么您应该将MaxMetaspaceSize设置为多大?首先计算平均预期的元空间使用量。作为第一个指导原则,您可以使用上面给出的数字,每个类有大约1K个类空间,每个class3个大约8K个非类空间,并将这些数字与您期望加载的类的数量相乘。

例如,如果您的应用程序计划加载10000个类,理论上您只需要10M的类空间,80M的非类空间。

现在你需要考虑一个安全裕度。因子2是大多数情况下的安全极限。当然,您可以降低级别并尝试运气,但要准备好通过更改代码或增加MaxMetaspaceSize来处理元空间OOM。

因子2将使我们拥有20M的类空间,160M的非类空间,总的元空间大小为180M。

 

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

关于

发表评论

表情 格式

暂无评论

登录

忘记密码 ?

切换登录

注册