如何分析Java 8压缩类空间中的内存泄漏?

Bas*_*sam 2 memory-leaks metadata jaxb out-of-memory java-8

一些上下文:我们已将Web应用程序的环境从在Java 7上运行升级到在Java 8和Tomcat 8上运行(64位arch,堆大小约2 GB,PermGen大小= 256 MB,对元空间大小没有约束).过了一会儿,我们开始收到以下错误:

java.lang.OutOfMemoryError:压缩的类空间

这意味着UseCompressedClassPointers所需的空间超出了CompressedClassSpaceSize.那时VisualVM显示了2 GB的元空间大小.

现在使用VisualVM工具,我们可以看到Metaspace大小随着每个请求大约3 MB而不断增加,但是堆似乎没有这样做.堆使用具有锯齿形状,在每个GC之后返回到相同的低点.

我可以告诉应用程序仅在使用Java JAXB操作时泄漏元数据,但我无法用VisualVM证明它.

该应用程序依赖于webservices-rt-1.4作为JAXB实现提供程序.该应用程序使用编组,解组.XSD的类生成是使用maven-jaxb2-plugin-0.13.1完成的.


更新:

在跟踪类加载和卸载之后,我发现WebAppClassLoader多次将相同的JAXB类加载到内存中,但从未清理过.而且,堆中没有实例.我调试了,我看到JDK通过反射调用方法javax.xml.bind.JAXBContext com.sun.xml.bind.v2.ContextFactory.createContext,这是在创建类时.

我虽然这些课程都是由GC清理的.是否负责清理classLoader?


问题:有没有办法分析元空间对象?为什么我在元空间中有泄漏而在堆中没有泄漏?他们不相关吗?这甚至可能吗?

为什么应用程序可以正常使用PermGen而不是Metaspace?

小智 5

我面临类似的问题.

在我的情况下,内存泄漏是由JAXBContext.newInstance(...)调用引起的.

解决方案: