一些上下文:我们已经将web应用程序的环境从运行在Java 7上升级到运行在Java 8和Tomcat 8上(64位arch,堆大小约2 GB,PermGen size=256 MB,不受元空间大小的限制)。过了一会儿,我们开始收到以下错误:
java.lang.OutOfMemoryError:压缩类空间
这意味着UseCompressedClassPointers所需的空间超过了CompressedClassSpaceSize。此时,VisualVM显示了一个2GB的元空间大小。
现在,使用VisualVM工具,我们可以看到Metaspace的大小随着每一个请求大约3MB而不断增加,但是堆似乎没有这样做。堆的使用有锯齿字形,在每个GC之后返回到相同的最低点。
我可以看出,只有在使用Java操作时,应用程序才会泄漏元数据,但我无法用VisualVM来证明它。
应用程序依赖于webservices-RT1.4作为JAXB实现提供者。应用程序使用编组、解编组。XSD的类生成是用maven-jaxb2-plugin-0.13.1完成的。
更新:
跟踪类加载和卸载之后,我发现同一个JAXB类被WebAppClassLoader多次加载到内存中,但从未清理过。此外,堆中没有它们的实例。我调试了JDK,我看到JDK是通过反射调用javax.xml.bind.JAXBContext javax.xml.bind.JAXBContext方法的,这就是创建类的时候。
我以为这些课是用GC清理的。清理卫生是classLoader的责任吗?
问题:有办法分析元空间对象吗?为什么我在metaspace中有漏洞,而在堆中没有泄漏呢?他们不是亲戚吗?这可能吗?
为什么这个应用程序可以在PermGen上正常工作,而不是Metaspace呢?
发布于 2016-12-22 13:14:13
我也面临着类似的问题。
在我的例子中,内存泄漏是由JAXBContext.newInstance(...)调用引起的。
解决方案:
-Dcom.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize=true VM参数,如在应答Old JaxB and JDK8 Metaspace OutOfMemory Issue中发布于 2018-03-13 14:25:48
我也有类似的问题,在setenv.sh中添加setenv.sh作为JVM参数来解决OOM元问题。
https://stackoverflow.com/questions/40346869
复制相似问题