【问题标题】:What is the use of MetaSpace in Java 8?Java 8 中的 MetaSpace 有什么用?
【发布时间】:2014-07-27 06:30:44
【问题描述】:

我知道他们在 Java 8 中已将 PermGen 替换为 MetaSpace。但我有几个问题:

  1. MetaSpace 是否默认被 GC 收集?
  2. 即使是 PermGen 也是通过添加 -XX:+CMSClassUnloadingEnabled 之类的 args 来收集的,那么 MetaSpace 有什么比 PermGen 更好的地方呢?
  3. MetaSpace 是基于原生内存的,所以它会将 java 对象保存在磁盘上而不是 VM 上?
  4. 甚至 MetaSpace 也会耗尽内存?如果再这样,我会得到OutOfMemoryException
  5. 默认情况下,MetaSpace 可以随着内存的增加而增长?

提前致谢

【问题讨论】:

    标签: java garbage-collection java-8


    【解决方案1】:

    MetaSpace默认是GC收集的吗?

    是的,当元空间满时,GC 会在元空间上运行,它也会 动态增加(允许)分配给的内存 元数据。

    连PermGen都加了​​-XX:+CMSClassUnloadingEnabled这样的args被GC收集了,那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,除非它达到限制,因此有必要为长时间运行的进程设置一个合理的限制。
    【解决方案2】:

    回应:

    1. 默认情况下,如果 Metaspace 内存达到 MaxMetaspaceSize,则会收集它。此参数最初是无限制的。限制是您机器中的内存。但是当不再需要类和类加载器时,内存会自动释放。如果您怀疑 ClassLoader 有内存泄漏,您只需要调整此参数。

    2. MetaSpece 使用本机内存,内存中的指针组织使得 GC 比旧的 PermGen 内存更快。

    3. 不,这意味着JVM像普通C程序一样使用内存,不使用Java对象的虚拟内存空间。那似乎内存仅受机器限制。如果需要,请注意机器的内存可以交换到磁盘。

    4. 如果设置MaxMetaspaceSize参数可以得到OutOfMemory,如果不设置这个参数可以得到进程是否分配了所有机器内存(包括交换空间)。

    【讨论】:

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

      一旦类元数据使用达到“MaxMetaspaceSize”(默认为"unlimited"),就会触发死类和类加载器的垃圾收集,因此需要进行适当的监控以限制此类 GC 的延迟或频率。

    2. 即使是 PermGen 也是通过添加 args 来收集的,例如 -XX:+CMSClassUnloadingEnabled,那是什么让 MetaSpace 比 PermGen 更好?

      主要目标是删除 permgen was 这样用户就不必考虑正确调整它的大小。

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

      磁盘不是本机内存而是存储设备。本机内存,在这种情况下是区域,是从 Java 堆中剩余的进程的内存

    4. MetaSpace 也会内存不足?

      是的,它受您机器内存量的限制。

    【讨论】:

    • 哈哈第2点让我笑了。今天我的一台生产服务器崩溃了两次,因为 Metaspace 使用了所有 RAM 并将其他所有内容都推送到交换。哦,没有让我想到如何调整元空间的大小:D
    猜你喜欢
    • 2015-01-23
    • 1970-01-01
    • 2014-07-21
    • 1970-01-01
    • 2019-11-12
    • 2015-05-28
    • 1970-01-01
    • 2018-06-19
    • 2017-01-18
    相关资源
    最近更新 更多