当前位置: 首页 > 知识库问答 >
问题:

java 8 java.lang.OutOfMemoryError:元空间

林夕
2023-03-14

我在运行Java cs应用程序时遇到OutOfMemoryError错误。根据错误消息,错误似乎是在将XML字符串传输到Java对象时发生的。

传输代码如下所示

public static Object convertXmlStrToObject(Class clazz, String xmlStr) {
    Object xmlObject = null;
    try {
        JAXBContext context = JAXBContext.newInstance(clazz);
        // 进行将Xml转成对象的核心接口
        Unmarshaller unmarshaller = context.createUnmarshaller();
        StringReader sr = new StringReader(xmlStr);
        xmlObject = unmarshaller.unmarshal(sr);
    } catch (JAXBException e) {
        e.printStackTrace();
    }
    return xmlObject;
}

我查看了日志,找到了触发此错误的字符串。然后,我使用上面的代码将这个字符串转换为java对象,大约转换了10万次。未报告任何错误。

我有数千个这样的应用程序在windows xp系统中运行,我担心这会导致一个巨大的问题。我谷歌了这个错误,很多人说这个错误发生是因为MaxMetaspaceSize太小,而我没有在我的应用程序中使用MaxMetaspaceSize。

java.lang.OutOfMemoryError: Metaspace
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl.<init>(Unknown Source)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl.newSAXParser(Unknown Source)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.getXMLReader(Unknown Source)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(Unknown Source)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(Unknown Source)
    at com.hgits.payCodeDebit.util.XMLUtil.convertXmlStrToObject(XMLUtil.java:91)

在检查最近的日志后,我发现了一个奇怪的问题。除了上面的错误,还有一个错误如下:

java.io.IOException: Map failed
at sun.nio.ch.FileChannelImpl.map(Unknown Source)
at sun.nio.ch.FileChannelImpl.transferFromFileChannel(Unknown Source)
at sun.nio.ch.FileChannelImpl.transferFrom(Unknown Source)
at org.apache.commons.io.FileUtils.doCopyFile(FileUtils.java:1147)
at org.apache.commons.io.FileUtils.copyFile(FileUtils.java:1091)
at org.apache.commons.io.FileUtils.copyFile(FileUtils.java:1038)
at com.hgits.cron.CheckNonFareParamJob.checkRecvParamList(CheckNonFareParamJob.java:153)
at com.hgits.cron.CheckNonFareParamJob.execute(CheckNonFareParamJob.java:54)
at org.quartz.core.JobRunShell.run(JobRunShell.java:213)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:557)
Caused by: java.lang.OutOfMemoryError: Map failed
at sun.nio.ch.FileChannelImpl.map0(Native Method)
... 10 more

谷歌搜索后,这似乎是一个记忆问题。我用jna和windows api GetProcessMemoryInfo搜索了进程内存。当我的应用程序启动时,jvm进程内存为615616K,这是正常的,一切都很好。运行大约36小时后,jvm进程内存达到1796676K,我开始出现“java.lang.OutOfMemoryError:Map failed”错误。当jvm进程内存达到1796676K时,我还记录了jvm的堆内存,该内存低于810942464byte(Runtime.getRuntime().maxMemory()):810942464byte(Runtime.getRuntime().totalMemory()):239632736byte(Runtime.getRuntime().freeMemory())。所以在jvm堆中仍然有200M freeMemory。

因为我用jna加载了几个dll,我的猜测是有些dll存在某种内存泄漏。如果我的猜测是正确的,我该如何找到原因?我尝试过jjvisualvm和jmc,但我没有看到任何错误。

共有1个答案

浦泳
2023-03-14

我能想到几个解释:

>

  • 某些 XML 解析器习惯于插入字符串。如果您正在执行大量XML解析,这会将大量字符串数据放入字符串池中...这是在元空间中。如果字符串仍然可访问(例如,因为DOM是可访问的,或者因为您将它们保存在另一个数据结构中),则可以填充元空间。

    在幕后,应用程序中的某些内容可能会进行大量的类加载。例如,如果广泛使用动态代理。这可以将许多不可收集的类放入元空间,最终填充它。

    动态代理(见上一点)可能是由< code>JAXBContext初始化创建的。正如@PaulBastide指出的,您应该能够创建一个单独的< code>JAXBContext并重用它。这样做不仅更有效,还可以解决元空间泄漏问题。

    增加元空间的大小是一个创可贴的解决方案。一个更好的想法是让JVM在OOME出现时创建一个堆转储,并分析该转储以找出是什么在使用如此多的元空间。然后决定这是一个您可以解决的问题,还是使用-XX:MetaspaceSize=…创可贴,并希望一切顺利。

    这已经很晚了,但是您导致<code>java.lang.OutOfMemoryError:Map failed</code>的问题不是普通的内存泄漏;i、 e.Java堆对象或本机堆对象泄漏。这可能根本不是泄漏。

    发生的事情是,您的代码正在尝试将文件映射到内存中。JVM要求操作系统提供一个大内存段来保存文件,操作系统说“不”。原因有很多:

    1. 您尝试映射的文件可能太大了。
    2. 您的应用程序可能已经映射了许多其他文件,但未能取消映射。(那将是泄漏。)
    3. 您的JVM进程可能有“ulimited”或类似的限制。
    4. 如果您正在运行32位JVM,您可能遇到了32位虚拟地址空间限制。

  •  类似资料:
    • JDK8中引入的元空间仍然是JVM中运行时数据区域的一部分?除了自动增加大小外,它与Permgen空间有何不同。?

    • 我在docker中运行的应用程序面临问题。出乎意料的是,它在30分钟后坠毁。当我的应用程序处理哪个缓存时,首先怀疑的是内存利用率。 我在应用程序启动时运行该命令,它显示元空间利用率为98%,这很奇怪。 所以我的问题是,这种利用率是否表明我的应用程序将98%的操作系统内存用于JVM进程,或者98%的操作系统内存可用于JVM?

    • 我一直试图创建一个宏来格式化从特定外部源复制的表,问题是,一些单元格似乎从右向左填充,剩余的空间向左填充空格:

    • 本文向大家介绍什么是空元素?常用的空元素有哪些?相关面试题,主要包含被问及什么是空元素?常用的空元素有哪些?时的应答技巧和注意事项,需要的朋友参考一下 没有闭合标签的元素是空元素

    • 问题内容: 区别在于我无法将注释添加到package- info.java,因为我们的所有JAXB类型都是从每次构建的模式中生成的。如果可能的话,我也更愿意不更改JAXB提供程序。 我想要实现的是设置一个空的String不会创建该元素,但是我需要为从许多模式中生成的所有JAXB类型设置它。有没有办法将其应用于所有生成的JAXB类中的所有String字段? 更新 我已经通过进行以下更改来设法为模式中

    • 我想我需要编辑临时表来将空单元格转换为空单元格。我可以从SSIS包中执行此操作吗?或者是否有可以使用的表设置? 谢谢你。