如何分析Java 8 compressed class space中的内存泄漏?
How to analyze memory leaks in Java 8 compressed class space?
一些上下文:我们已将 Web 应用程序的环境从 Java 7 上的 运行 升级到 Java 8 和 Tomcat 8 上的 运行 (64 位架构,堆大小约为 2 GB,PermGen 大小=256 MB,对 metaspace 大小没有限制)。过了一会儿,我们开始收到以下错误:
java.lang.OutOfMemoryError: 压缩 class space
这意味着 UseCompressedClassPointers 所需的 space 超过了 CompressedClassSpaceSize。在那一刻,VisualVM 显示了 2 GB 的元space 大小。
现在使用 VisualVM 工具,我们可以看到 Metaspace 大小随着每个请求不断增加大约 3 MB,但是堆似乎没有这样做。每次 GC 后,堆使用呈锯齿状,回到相同的低点。
只有在使用 Java JAXB 操作时,我才知道应用程序正在泄漏元数据,但我无法用 VisualVM 证明这一点。
应用程序依赖 webservices-rt-1.4 作为 JAXB 实现提供程序。该应用程序使用编组、解组。来自 XSD 的 class 生成是使用 maven-jaxb2-plugin-0.13.1 完成的。
更新:
跟踪class加载和卸载后,我发现相同的JAXB classes被WebAppClassLoader多次加载到内存中,但从未清理过。此外,堆中没有它们的实例。我进行了调试,发现 JDK 正在调用该方法
javax.xml.bind.JAXBContext com.sun.xml.bind.v2.ContextFactory.createContext 通过反射,那是创建 class 的时候。
虽然 classes 已被 GC 清理。 classLoader 负责清理吗?
问题:有没有办法分析元space对象?为什么我在 metaspace 中有泄漏但在堆中没有?他们没有关系吗?这可能吗?
为什么应用程序可以与 PermGen 一起正常工作,但不能与 Metaspace 一起工作?
我遇到了类似的问题。
在我的例子中,内存泄漏是由 JAXBContext.newInstance(...)
调用引起的。
解决方案:
- 将这个新实例包装为单例 (https://github.com/javaee/jaxb-v2/issues/581) 或
- 使用
-Dcom.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize=true
VM 参数,如回答
我有类似的问题,在 setenv.sh 中添加 -Dcom.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize=true 作为 JVM OPT 参数,它解决了 OOM 元空间问题。
一些上下文:我们已将 Web 应用程序的环境从 Java 7 上的 运行 升级到 Java 8 和 Tomcat 8 上的 运行 (64 位架构,堆大小约为 2 GB,PermGen 大小=256 MB,对 metaspace 大小没有限制)。过了一会儿,我们开始收到以下错误:
java.lang.OutOfMemoryError: 压缩 class space
这意味着 UseCompressedClassPointers 所需的 space 超过了 CompressedClassSpaceSize。在那一刻,VisualVM 显示了 2 GB 的元space 大小。
现在使用 VisualVM 工具,我们可以看到 Metaspace 大小随着每个请求不断增加大约 3 MB,但是堆似乎没有这样做。每次 GC 后,堆使用呈锯齿状,回到相同的低点。
只有在使用 Java JAXB 操作时,我才知道应用程序正在泄漏元数据,但我无法用 VisualVM 证明这一点。
应用程序依赖 webservices-rt-1.4 作为 JAXB 实现提供程序。该应用程序使用编组、解组。来自 XSD 的 class 生成是使用 maven-jaxb2-plugin-0.13.1 完成的。
更新:
跟踪class加载和卸载后,我发现相同的JAXB classes被WebAppClassLoader多次加载到内存中,但从未清理过。此外,堆中没有它们的实例。我进行了调试,发现 JDK 正在调用该方法 javax.xml.bind.JAXBContext com.sun.xml.bind.v2.ContextFactory.createContext 通过反射,那是创建 class 的时候。
虽然 classes 已被 GC 清理。 classLoader 负责清理吗?
问题:有没有办法分析元space对象?为什么我在 metaspace 中有泄漏但在堆中没有?他们没有关系吗?这可能吗?
为什么应用程序可以与 PermGen 一起正常工作,但不能与 Metaspace 一起工作?
我遇到了类似的问题。
在我的例子中,内存泄漏是由 JAXBContext.newInstance(...)
调用引起的。
解决方案:
- 将这个新实例包装为单例 (https://github.com/javaee/jaxb-v2/issues/581) 或
- 使用
-Dcom.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize=true
VM 参数,如回答
我有类似的问题,在 setenv.sh 中添加 -Dcom.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize=true 作为 JVM OPT 参数,它解决了 OOM 元空间问题。