Java中的元数据GC阈值

2025/04/26

1. 概述

垃圾回收是Java运行时系统识别并删除内存中未引用对象的过程,它通过清除未引用的对象、临时对象、未使用的元数据等,在内存管理中发挥着至关重要的作用。

在本教程中,我们将探索元空间和元数据GC阈值,以及如何调整它们的参数。

2. 元数据

元数据包含堆中对象的信息,包括它们的类定义、方法表和相关信息。根据Java版本的不同,JVM会将这些数据存储在永久代或元空间(Metaspace)中。

JVM依靠这些信息来执行类加载、字节码验证和动态绑定等任务。

3. PermGen和Metaspace

从Java 8开始,JVM用内存中一个名为“元空间”的新区域来存储元数据,从而取代了永久代或PermGen

PermGen是一个固定大小的内存区域,独立于主堆,用于存储JVM加载的类和方法的元数据。它有一个固定的最大大小,一旦满了,JVM就会抛出OutOfMemoryError。

元空间的大小并非固定不变,可以根据应用程序中元数据的数量动态增长。元空间独立于主堆,位于一段本机内存(进程内存)中,它的大小仅受主机操作系统的限制。

4. 元数据GC阈值

在Java中,当我们创建一个带有元数据的对象时,它会像其他对象一样占用内存空间,JVM需要这些元数据来执行各种任务。与常规对象不同,元数据在达到特定阈值之前不会被垃圾回收。

随着Java程序执行过程中越来越多的类被动态加载,元空间就会被填满

JVM维护元空间内容大小的阈值,当特定分配不符合该阈值时,它会触发元数据GC阈值垃圾回收周期。

5. 元数据的JVM参数

我们可以使用JVM标志(如-XX:+PrintClassHistogram和-XX:+PrintMetaspaceStatistics)来收集有关使用大量元数据内存的类的信息,并打印有关Metaspace的统计信息,例如用于类元数据的空间量。

利用这些信息,我们可以优化代码,提高元空间和垃圾回收周期的利用率。此外,我们还可以调整与元空间相关的JVM参数。

我们来看一下用于调整元数据和元空间的一些JVM参数。

5.1 -XX:MetaspaceSize=<size>

此参数用于设置分配给类元数据的初始空间量(初始高水位线)(以字节为单位),这些空间量可能引发垃圾回收并卸载类。该值是近似值,这意味着JVM也可以决定增加或减少元空间的大小。

此参数的值较大时,可确保垃圾回收发生的频率较低,该参数的默认值取决于平台,范围从12MB到20MB左右。

例如,我们可以将其设置为128兆字节:

-XX:MetaspaceSize=128m

5.2 -XX:MaxMetaspaceSize=<size>

此参数设置Metaspace的最大大小,超过此大小将引发OutOfMemory错误,此标志限制分配给类元数据的空间量,分配给此参数的值是近似值。

默认情况下,没有设置限制,这意味着Metaspace可以增长到可用本机内存的大小

作为示例,我们将其设置为100兆字节:

‑XX:MaxMetaSpaceSize=100m

5.3 -XX:+UseCompressedClassPointers

功能旨在通过压缩对象引用来减少64位Java应用程序的内存占用,当此参数设置为true时,JVM将对类元数据使用压缩指针,这使得JVM能够对类相关数据使用32位寻址,而不是使用完整的64位指针。

这种优化在64位架构上尤其有价值,因为它减少了类元数据的内存使用量以及对象引用所需的内存,从而有可能提高应用程序的整体性能。

压缩类指针将类空间分配与非类空间分配区分开,因此,我们有两个全局元空间上下文:一个保存Klass结构的分配(压缩类空间),另一个保存其他所有内容(非类元空间)。

值得注意的是,在最近版本的JVM中,运行64位Java应用程序时通常默认启用该标志,因此我们通常不需要明确设置此标志。

5.4 -XX:+UseCompressedOops

此JVM标志用于启用或禁用64位JVM中Java对象使用压缩指针的功能,当该参数设置为true时,JVM将使用压缩指针,这意味着对象引用将使用32位指针,而不是完整的64位指针。

使用压缩指针,只能寻址较小范围的内存,这迫使JVM使用较小的指针来节省内存。

6. 总结

在本文中,我们探讨了元数据和元空间的概念。

我们探讨了触发元数据GC阈值的原因,此外,我们还了解了元数据GC阈值以及可用于调整元空间和优化垃圾回收周期的不同JVM参数。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章