在运行Java应用程序时,我有一个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对象,因为报告了10K的times.No错误。
我在windows系统中运行了数千个这样的应用程序,我担心这可能会导致一个巨大的问题。我在谷歌上搜索了这个错误,很多人说这个错误是因为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标记了进程内存。当我的应用程序启动时,jvm进程内存是615616K,这是正常的,一切正常。运行大约36个小时后,jvm进程内存达到1796676K,我开始出现“java.lang.OutOfMemoryError: Map失败”错误。当jvm进程内存达到1796676K时,我还记录了jvm的堆内存,如下所示: 810942464byte(Runtime.getRuntime().maxMemory()):810942464byte(Runtime.getRuntime().totalMemory()):239632736byte(Runtime.getRuntime().freeMemory()).因此,jvm堆中仍然有200M freeMemory。
因为我使用jna加载了几个dll,所以我猜其中一些dll中存在某种内存泄漏。如果我的猜测是正确的,我该如何定位原因呢?我尝试过jjvisualvm和jmc,但是我没有发现任何问题。
发布于 2018-05-21 11:18:33
我能想到几个解释:
JAXBContext初始化创建的。正如一个@PaulBastide所指出的,您应该能够创建单个JAXBContext并重用它。这样做不仅效率更高,还可以解决元空间泄漏问题。增加metaspace的大小是一个创可贴解决方案。一个更好的想法是让JVM在OOME的时候创建一个堆转储,并分析转储,找出什么使用了这么多元空间。然后决定它是否是一个问题,你可以解决,或是否使用-XX:MetaspaceSize=...的创可贴和希望的最好。
这已经很晚了,但是导致java.lang.OutOfMemoryError: Map failed的问题并不是普通的内存泄漏,即Java堆对象或本机堆对象的泄漏。这可能根本不是泄密。
正在进行的是,您的代码正在尝试将文件映射到内存中。JVM要求OS提供一个大内存段来保存文件,而OS说“不行”。造成这种情况的原因有以下几个:
https://stackoverflow.com/questions/50447081
复制相似问题