繁体   English   中英

元空间增长、死类加载器和 GC

[英]Metaspace growth, dead classloader and GC

我们遇到这样一种情况,其中 springboot 微服务的元空间不断增长,但堆运行良好。

jmap -clstats 显示有大量以下类型的死类加载器。

0x00000000e3c8e3c8 1 4087 0x00000000e0004d18死 com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl$TransletClassLoader@0x000000010087c7e8

在最初的高水位线 GC 被触发,我看到元空间下降。 在由于定义的元空间大小而触发的强制 GC 之后,我看到元空间不断增长,并且我看到更多相同类型的死类加载器保留在元空间中。 我确实看到了一些 GC 活动,但元空间消耗没有下降。 但是,如果我通过 visualvm 强制 GC 收集,大量类将被卸载,元空间消耗将返回到服务启动时的 state。

为什么 JVM 托管 GC 不会卸载这些死掉的类加载器,而强制 GC 会卸载这些加载器? 如果弱/软/幻象引用是原因,那么它不应该也适用于强制 GC 吗?

这是在 Java8 上。 任何人都可以就我接下来应该看的地方给出一些指示吗? 显然存在泄漏,那么有没有办法知道 TemplatesImpl$TransletClassLoader 的父类加载器?

感谢任何帮助。

首先,JVM 只会在 Full GC 期间清除 Metaspace,而不会在 Young GC 期间清除。 所以你看到的行为是意料之中的。

在最初的高水位线 GC 被触发,我看到元空间下降。

如果您检查 GC 跟踪,您将看到一个 System.GC() 调用。 那就是 Full GC。

但是,如果我通过 visualvm 强制 GC 收集,大量类将被卸载,元空间消耗将返回到服务启动时的 state。

同样,这将是一次由 visualvm 触发的 Full GC,可以在 GC trace 中看到。 这就是您看到利用率下降的原因。

根据您提供的描述,我认为您没有类加载器泄漏,因为所有内容都在 Full GC 期间被清理。 根据我的经验,如果应用程序不必要地使某些对象保持活动状态,因此不会被垃圾收集,我只会将其视为“内存泄漏”——即使在 Full GC 期间也是如此。 在您的情况下,我建议使用-XX:MaxMetaspaceSize标志来限制元空间大小。 当占用率达到该阈值时,JVM 将自动触发 Full GC,正如您所注意到的,元空间的使用率将下降。 明智地设置该限制,因为太低的值会导致java.lang.OutOfMemoryError: Metaspace问题。

可以在此处找到有关元空间的更多详细信息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM