从Java 7迁移到Java 8后,出现了java.lang.OutOfMemoryError: Metaspace错误。

7

我们在升级后出现了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。

我想知道为什么在类加载方面需要更多的Metaspace,因为服务器和应用程序相同,版本只是更改了Java。


你有这个错误的堆栈跟踪吗?我想知道OOM的确切错误。 - kucing_terbang
1
你能提供在使用Java 8启动JBoss时所需的确切Java参数吗? - DevDio
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 - Valsaraj Viswanathan
2个回答

8
您可能需要完全删除-XX:MaxMetaspaceSize=512m
我猜,在Java 7中,您需要增加永久代才能使所有内容运行,因为默认的最大值太低了。
在Java 8中,保存类的元空间默认情况下可以无限扩展,因此您可能不会遇到首先为Java 7解决的问题。相反,正如您已经经历过的,您会遇到另一个问题:设置过低的元空间限制。删除该限制可能会解决该问题,并允许JVM为您做出适当的决策。
请参阅此答案

移除MaxMetaspaceSize导致Metaspace使用量增加到3g。由于服务器有8g并且最大堆分配为7g,因此发生了另一次内存崩溃。在metaspace中死亡的类加载器是否被垃圾回收?是否有任何设置来控制这个问题? - Valsaraj Viswanathan
1
你可以尝试设置-XX:MaxMetaspaceExpansion=0来强制进行元空间垃圾回收(参见https://dev59.com/zI3da4cB1Zd3GeqPyVIL#31632341),但如果有人仍然持有你的类对象,那么这样做也不会有太大的好处。 - Hendrik
即使将-XX:MaxMetaspaceExpansion=0设置为0,结果仍然相同。总数=1394 27716 53490569 N/A alive=1,dead=1393 N/A。我看到垃圾收集在非堆内存上频繁运行。我想知道为什么会有这么多死亡的类加载器? - Valsaraj Viswanathan
1
这听起来像是你需要调试一个类加载内存泄漏问题。也许 https://dev59.com/fVoU5IYBdhLWcg3wAjjV#37933050 能够帮助一点。此时我会在网上搜索关于 Java 8 上 JBoss 4.2 类加载问题的信息。由于 v4.2 比 Java 8 更旧,所以可能会有所不同。也许现在是更新 JBoss 的时候了。 - Hendrik

2

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接