Java 8:为什么Metaspace大小增加,但加载的类数保持不变?

22

在我们的应用程序中,使用Jdk 8,我们使用VisualVM来跟踪加载类的使用情况和元空间的使用情况。

在我们的应用程序运行的某个时刻,我们发现加载类的数量不再增加,但是元空间的大小仍然会随着程序的运行而增加。除了类之外,还有什么存储在元空间中可能导致这种情况?


2
我猜,虽然已加载的类数量停滞不前,但实际使用的代码量仍可能增加... - Holger
嗯,我不明白你的意思。类的代码已经在那里了,还应该放什么? - Chris W.
5
你认为JVM是否以跟硬盘上类文件所在位置相同的方式将类存储在RAM中?元信息是通过分析或处理类文件内容得出的,这项工作(或其中的某些部分)可能会推迟到方法真正被使用时才进行。 - Holger
啊,你说得对。也许被Hotspot编译的本地代码也会在那里呢? - Chris W.
编译成本地代码的好文章在这里:https://dev59.com/B2Up5IYBdhLWcg3w1aF7。 - Chris W.
2
不确定这个。但我知道编译后的代码会进入“CodeCache”区域,与MetaSpace无关。你是否经常使用反射(或像Spring这样的框架)?可能会有关于代理(方法句柄等)的元信息存储在Metaspace中,这些不算作已加载的类。 - mabi
2个回答

10

当您的程序运行时,HotSpot的JIT编译器可能会确定您代码中的某些部分为“热点”。这将导致这些部分被转换/编译为本地代码,并且还可能将一些其他代码内联到其中。这种本地代码表示必须放在某个地方,它与其他类元数据一样存储在元空间中。

这解释了您所看到的持续增长:随着时间的推移,使用简单的指标来判断哪些代码片段执行次数最多,越来越多的代码片段将被JIT编译,因为它们将达到-XX:CompileThreshold(默认为10000)设置的阈值。


0

我不确定,但是在这里(http://java.dzone.com/articles/java-8-permgen-metaspace)我找到了这个信息

当类元数据使用量达到“MaxMetaspaceSize”时,死亡类和类加载器的垃圾回收会被触发。

也许这就是增加元空间大小的原因。


OP明确表示加载的类数量不再增加。因此,无论是死亡还是存活,总数应该保持稳定。 - mabi

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