元数据GC阈值是什么,如何进行调优?

40
在我的应用程序中,我有以下的 -verbose:gc
[GC (Metadata GC Threshold)  8530310K->2065630K(31574016K), 0.3831399 secs]
[Full GC (Metadata GC Threshold)  2065630K->2053217K(31574016K), 3.5927870 secs]
[GC (Metadata GC Threshold)  8061486K->2076192K(31574016K), 0.0096316 secs]
[Full GC (Metadata GC Threshold)  2076192K->2055722K(31574016K), 0.9376524 secs]
[GC (Metadata GC Threshold)  8765230K->2100440K(31574016K), 0.0150190 secs]
[Full GC (Metadata GC Threshold)  2100440K->2077052K(31574016K), 4.1662779 secs]

这个"元数据垃圾回收阈值"是什么,如何降低它。注意:尽管Full GC花费了很长时间进行清理,但实际上清理的内容并不多,也就是说,最好不要这样做。

2个回答

52

这条日志信息说明GC是由于Metaspace分配失败引起的。 Metaspaces保存类元数据,它们在Java 8中出现以替换PermGen

以下是一些调整Metaspaces的选项。
您可以设置以下一个或多个选项:

-XX:MetaspaceSize=100M 设置分配的类元数据空间大小,当第一次超出时会触发垃圾回收;

-XX:InitialBootClassLoaderMetaspaceSize=32M 增加引导类加载器Metaspace的大小;

-XX:MinMetaspaceFreeRatio=50 使Metaspaces更积极地增长;

-XX:MaxMetaspaceFreeRatio=80 减少Metaspaces缩小的机会;

-XX:MinMetaspaceExpansion=4M 是 Metaspace 扩展的最小大小;

-XX:MaxMetaspaceExpansion=16M 是在没有 Full GC 的情况下可以扩展 Metaspace 的最大大小。


4
JDK8中的Metaspace默认设置为21MB,适用于64位虚拟机。对于高性能应用程序,您可能需要考虑将最小和初始大小设置为最大值(就像在JDK7中的PermGen一样),并限制高水位线大小比率。Metaspace Full GC是昂贵的,因为它会运行一个Old Heap Full GC,从而增加了应用程序的p95、p99运行时间延迟,原因是GC暂停时间变长。-XX:MetaspaceSize=1024m -XX:MaxMetaspaceSize=1024m -XX:MinMetaspaceFreeRatio=0 -XX:MaxMetaspaceFreeRatio=100 - ak_2050
1
似乎大多数选项在java8的man页面(http://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html)中没有记录,而您发布的文章是2014年的,这些选项被删除了还是只是未记录? - mgrandi
1
@mgrandi 这些标志从未列在该页面上。大多数虚拟机标志没有很好的文档说明,而是在源代码或博客文章中。 - apangin
@Eugene 这个答案���在 JDK-8151845 之前写的。如果你愿意,随意编辑。 - apangin

20

虽然已经有了一个可接受的答案,但需要提到以下内容:

-XX:MaxMetaspaceSize=<NNN> 其中<NNN>是为类元数据分配的最大空间(以字节为单位)。

此外在这里,

死亡类和类加载器的垃圾回收将在类元数据使用达到“MaxMetaspaceSize”时触发。

此文章中列出了可用选项列表。


2
这个回答比被接受的回答更加精确地回答了这个问题。 - kubanczyk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接