2017-08-11 128 views
2

升级后,我们得到OutOfMemoryError。 JVM设置保持与Java 7一样正常工作。java.lang.OutOfMemoryError:从Java 7迁移到Java 8后出现Metaspace错误

这里是Jboss的4.2服务器的设置:在Java 7中

-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

唯一的区别是XX:MaxMetaspaceSize =512米与PermGen的最大被取代。

我想知道为什么它需要更多的Metaspace进行类加载,因为服务器&应用程序是相同的&只是Java版本中的更改。

+0

你有错误的堆栈跟踪?我想知道OOM的确切错误。 –

+1

当您使用Java 8启动JBoss时,您能否提供确切的Java参数? – DevDio

+0

所使用的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 –

回答

1

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

+0

部署的代码没有使用lambda表达式。 –

3

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

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

在Java 8中,持有类的元空间可以在默认情况下无限制地扩展,因此您可能不会遇到您首先尝试为Java 7解决的问题。相反,正如您所经历的那样,您会遇到另一个问题:设置太低的元空间限制。消除所述限制可能会解决问题并允许JVM为您做出适当的决定。请参阅this answer

+0

删除MaxMetaspaceSize导致Metaspace使用量增加至3g。由于服务器以7g分配了8g&max堆,因此导致另一个内存崩溃。 metaspace垃圾中的死垃圾类加载器是否被收集? Os有没有任何设置来控制它? –

+1

您可以尝试设置'-XX:MaxMetaspaceExpansion = 0'来强制元空间垃圾回收(请参阅https://stackoverflow.com/a/31632341/942774),但如果有人仍然坚持您的类对象, t做得很好。 – hendrik

+0

即使设置了-XX:MaxMetaspaceExpansion = 0,结果也是一样的。 total = 1394 27716 53490569 N/A alive = 1,dead = 1393 N/A。我看到垃圾收集频繁地在非堆内存中运行。我想知道为什么这些死了的班级装载机呢? –