ChatGPT解决这个技术问题 Extra ChatGPT

Java 8 中的 MetaSpace 有什么用?

我知道他们已经用 Java 8 中的 MetaSpace 替换了 PermGen。但我有几个问题:

MetaSpace默认是GC收集的吗?甚至 PermGen 也是通过添加 -XX:+CMSClassUnloadingEnabled 之类的 args 来收集的,那么 MetaSpace 有什么比 PermGen 更好的呢? MetaSpace 是基于本地内存的,所以它把 java 对象保存在磁盘上而不是 VM 上?甚至 MetaSpace 也会内存不足?如果再次这样,我将得到 OutOfMemoryException。默认情况下,MetaSpace 可以随着内存的增加而增长?


H
Hearen

MetaSpace默认是GC收集的吗?

是的,GC 将在其满时在元空间上运行,它还将动态增加(允许)为元数据分配的内存。

甚至 PermGen 也是通过添加 -XX:+CMSClassUnloadingEnabled 之类的 args 来收集的,那么 MetaSpace 有什么比 PermGen 更好的呢?

改进在于元空间的动态扩展,这是 permgen 无法做到的。

MetaSpace 是基于本地内存的,所以它把 java 对象保存在磁盘上而不是 VM 上?

根据元空间的描述,它只使用本机内存(无分页)。

根据 Pierre - Hugues Charbonneau (link here) 的研究,很明显,元空间的引入并不一定能解决 OOM 问题,它充其量只是解决问题的方法,它试图动态调整元空间内存的大小以适应越来越多的类被加载,可能会导致无法控制的增长(只要本机内存允许)。

我们可以通过将 MaxMetaspaceSize 参数设置为 JVM 并运行提供的示例程序来实现著名的 OOM 错误。

非常感谢 Pierre-Hugues Charbonneau。


是的,GC 将在其满时在元空间上运行,它还将动态增加(允许)为元数据分配的内存。 GC会用完堆是正常的吗?
拥有 GC 的想法是为了防止这种情况.. 但它可能会接近满,然后 GC 启动.. 但这可以通过智能内存配置和合理的编码来防止.. 还有大量的 RAM 可以延长不可避免的时间:)
改进在于元空间的动态扩展,这是 permgen 无法做到的。您是说 permgen 不能扩展而元空间可以吗?它们都可以通过提供参数来限制。那么为什么元空间是可扩展的呢?
@ernesto 如果您没有指定元空间的上限,它将尽可能地扩展(并且可能)。
从我自己看到的情况来看,除非它达到限制,否则它似乎不是 GCd,因此有必要为长时间运行的进程设置一个合理的限制。
F
Fernando Rincon

作为回应:

默认情况下,如果 Metaspace 内存达到 MaxMetaspaceSize,则会收集它。此参数最初是无限的。限制是您机器中的内存。但是当不再需要类和类加载器时,内存会自动释放。如果您怀疑 ClassLoader 有内存泄漏,您只需要调整此参数。 MetaSpece 使用本机内存,内存中的指针组织使得 GC 比旧的 PermGen 内存更快。不,这意味着 JVM 像普通 C 程序一样使用内存,并且不为 java 对象使用虚拟内存空间。那似乎内存仅受机器限制。请注意,如果需要,可以将机器的内存交换到磁盘。如果你设置参数 MaxMetaspaceSize 你可以得到 OutOfMemory ,如果你不设置这个参数你可以得到进程是否分配了所有的机器内存(包括交换空间)。


如果它到达 MetaspaceSize 而不是 MaxMetaspaceSize
元空间绝对不会去交换(在 Linux 64 位的 Java 8u60 上测试它)。在泄漏时,它可以推动其他所有内容进行交换,从而使机器停止运行。
@JigarJoshi 我刚刚测试过,如果 Metaspace 到达 MaxMetaspaceSize 而不是 MetaspaceSize,则默认收集 Metaspace。
@kubanczyk,你错了。 Java 元空间可以交换。显然,如果它被广泛使用,那么其他应用程序的内存将被交换。 “直接记忆”可能会被误解,其含义取决于上下文。这里的意思是“不是java虚拟内存,而是os内存”。但在 RAM 和 SWAP 中分配的是“操作系统虚拟内存”。在 Linux 中,只有特权用户才能直接在 RAM 中分配内存(请参阅 kmalloc)。 JAVA 是一个用户态进程(我认为它利用了 mmap)。
@mcoolive 在实践中,我的 Linux 服务器因一些元空间(即类/加载器)泄漏而被多次关闭。在 Linux 中,用户态程序可以固定虚拟内存,因此它始终保留在 RAM 中。我的 16 GB 的类没有被广泛使用,并且是由非 root 用户分配的,但没有一个字节被换出。操作系统的重要部分在压力下被换掉,这导致了中断。
T
Tiny

MetaSpace默认是GC收集的吗?一旦类元数据使用量达到“MaxMetaspaceSize”,默认为“无限制”,就会触发死类和类加载器的垃圾收集,因此需要适当的监控来限制此类 GC 的延迟或频率。甚至 PermGen 也是通过添加 -XX:+CMSClassUnloadingEnabled 之类的 args 来收集的,那么 MetaSpace 有什么比 PermGen 更好的呢?主要目标是删除 permgen,以便用户不必考虑正确调整它的大小。 MetaSpace 是基于本地内存的,所以它把 java 对象保存在磁盘上而不是 VM 上?磁盘不是本机内存,而是存储设备。本机内存,在这个上下文中是区域,是Java堆中剩余的进程的内存,甚至MetaSpace可以用完内存吗?是的,它受机器内存量的限制。


哈哈第2点让我笑了。今天我的一台生产服务器崩溃了两次,因为 Metaspace 使用了所有 RAM 并将其他所有内容都推送到交换。哦,这不是让我想到如何调整元空间的大小:D