如何诊断Java 8元空间泄漏?

38

我有一个J2EE应用程序,它表现出一些有趣的行为...堆似乎表现良好,在随着时间的推移进行垃圾回收时增长和缩小。没有明显的长期堆扩展 。然而,元空间只是稳定地每小时增长约20Mb,直到我们达到MaxMetaspace并遇到OOME。我尝试了并行和G1垃圾收集器(jdk1.8.0_40)。

该应用程序在执行过程中未被重新部署,因此似乎不像是典型的类加载器泄漏。 有人有建议如何追踪此泄漏源吗?


你已经找到任何答案了吗? - Ricardo Mogg
你能提供更多信息吗:JEE服务器,使用的库。 - sibnick
1
这是尝试在Java 8下在JBoss 4.2.3.GA上运行传统的J2EE应用程序的一次尝试。这不是支持的配置,但客户真的想尝试一下。我知道自那时以来JBoss类加载器发生了重大变化,所以我怀疑它是一个类加载器问题。Phillipe以下关于代理生成的猜测可能有一些价值。我们最终决定“咬紧牙关”,将应用程序移植到Wildfly 8。 - It Worked Yesterday
1
我也遇到了类似的问题,我们使用的是Wildfly 10,在多次重新部署应用程序后,会抛出Metaspace oom错误。增加最大Metaspace只是一种解决方法,而不是解决方案。我还没有找到任何解决方案。 - Dmitry Avgustis
2个回答

7
做一个堆转储并使用Eclipse MAT进行分析。查看您加载的类。检查是否有意外的内容,特别是重复的类。它还具有类加载器浏览器。
编辑: 理论上,您也可能不断生成代理。

1
我们尝试了MAT类加载器浏览器。不幸的是,该应用程序足够繁忙和复杂,并且泄漏速度足够缓慢,以至于仍然是“大海捞针”的问题。这个配置本来就是一个过渡性解决方案,而且我们已经到了收益递减的点,所以我们放弃了。 - It Worked Yesterday
我不知道WildFly的问题。 OP从未调试过这个问题,所以可能是任何东西,包括他/她的应用程序。 - Philippe Marschall

7

java.lang.OutOfMemoryError: Metaspace的主要原因是:

  • 加载到Metaspace中的类太多或者
  • 加载到Metaspace中的类太大

如果想要重现这个问题,请使用以下代码片段:

public class Metaspace {
static javassist.ClassPool cp = javassist.ClassPool.getDefault();

public static void main(String[] args) throws Exception {
    for (int i = 0; ; i++) { 
        Class c = cp.makeClass("eu.plumbr.demo.Generated" + i).toClass();
    }
  }
}

所有这些生成的类定义最终都会占用Metaspace。
Javaassist在Maven仓库中。
您可以在这里找到更多关于OOME的信息。

你好,我在清理javassist.ClassPool对象时遇到了问题。如何解决这个问题? - Grayden Hormes

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