【问题标题】:java.lang.OutOfMemoryError: Metaspace error after migrating to Java 8 from Java 7java.lang.OutOfMemoryError:从 Java 7 迁移到 Java 8 后出现元空间错误
【发布时间】:2017-08-11 09:55:00
【问题描述】:

升级时出现 OutOfMemoryError。 JVM 设置与运行良好的 Java 7 保持一致。

这是 Jboss 4.2 服务器中的设置:

-server -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 -Xms4096m -Xmx7168m -XX:MaxMetaspaceSize=512m -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled - Djava.security.egd=file:///dev/urandom

Java 7 中唯一的区别是 XX:MaxMetaspaceSize=512m 被替换为 PermGen max。

我想知道为什么它需要更多的元空间来加载类,因为服务器和应用程序是相同的,只是 Java 版本有所不同。

【问题讨论】:

  • 你有错误的堆栈跟踪吗?我想知道 OOM 的确切错误。
  • 用Java 8启动JBoss时能否提供准确的Java参数?
  • 使用的Java参数被添加到查询中:-server -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 -Xms4096m -Xmx7168m -XX:MaxMetaspaceSize =512m -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -Djava.security.egd=file:///dev/urandom

标签: java java-8 out-of-memory


【解决方案1】:

您可能应该完全删除 -XX:MaxMetaspaceSize=512m。

我的猜测是,在 Java 7 中,您需要增加永久代才能运行,因为默认的最大值太低了。

在 Java 8 中,保存您的类的元空间默认情况下可以无限制地扩展,因此您可能不会遇到最初尝试为 Java 7 解决的问题。相反,正如您所经历的那样,您遇到了另一个问题:将元空间限制设置得太低。删除上述限制可能会解决问题并允许 JVM 为您做出合适的决定。

另见this answer。

【讨论】:

  • 删除 MaxMetaspaceSize 导致 Metaspace 使用量增加到 3g。由于服务器在 7g 中分配了 8g 和最大堆,因此又发生了一次内存崩溃。元空间垃圾中的死类加载器是否被收集?是否有任何设置可以控制它?
  • 你可以尝试设置-XX:MaxMetaspaceExpansion=0 来强制元空间垃圾回收(见stackoverflow.com/a/31632341/942774),但是如果有人仍然持有你的类对象,它不会有多大好处。
  • 即使设置-XX:MaxMetaspaceExpansion=0,结果也是一样的。总计 = 1394 27716 53490569 N/A 活着=1,死了=1393 N/A。我看到垃圾收集在非堆内存上频繁运行。我想知道为什么会有这么多死掉的类加载器呢?
  • 这听起来像你需要调试一个类加载内存泄漏。也许stackoverflow.com/a/37933050/942774 有点帮助。此时我会在网上搜索 Java 8 上的 JBoss 4.2 类加载问题。YMMV,因为 v4.2 比 Java 8 更早。也许是时候更新 JBoss 了。
【解决方案2】:

我想到的一件事是 java8 使用 lambda,每个 lambda 都是 java 8 中的某种类。如果我错了,请纠正我,但这就是我在创建 java8 应用程序的类图表时所看到的。因此 java8 使用了更多的类内存。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多