jelly wang
jelly wang

Reputation: 1

java 8 java.lang.OutOfMemoryError: Metaspace

I'm having an OutOfMemoryError while running Java cs application. According to the error message,it seems that the error occurs while doing transferring XML String to Java object.

The transfer code is below

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;
}

I have looked into my logs and located the String which triggered this error. Then I convert this String into java object using the code above for like 10K times.No error was reported.

I have thousands of such applications running in windows xp system and I worried that this may cause a huge problem. I Googled this error and many says that the error occurs because the MaxMetaspaceSize is too small,while i didn't use the MaxMetaspaceSize in my application.

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)

After checking recent logs,I found a strange problem. Besides the error above, there is another error which is below:

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

After Googling,this seemed to be a memory problem. I looged the process memory with jna and windows api GetProcessMemoryInfo. When my application started, the jvm process memory is 615616K which is normal and everything is ok. After running about 36 hours , the jvm process memory reached 1796676K,and I start to have “java.lang.OutOfMemoryError: Map failed” error. While the jvm process memory reached 1796676K, I also logged the heap memory of jvm which is as below 810942464byte(Runtime.getRuntime().maxMemory()):810942464byte(Runtime.getRuntime().totalMemory()):239632736byte(Runtime.getRuntime().freeMemory()). So there is still 200M freeMemory in jvm heap.

Because I used jna to load several dll,My guess is that there is some kind of memory leak in some of the dll. If my guess is right, how can I locate the cause? I have tried jjvisualvm and jmc,but I see nothing wrong.

Upvotes: 0

Views: 13168

Answers (1)

Stephen C
Stephen C

Reputation: 719436

I can think of a couple of explanations:

  1. Some XML parsers are in the habit of interning strings. If you are doing a lot of XML parsing, this put a lot of string data into the string pool ... which is in meta-space. If the strings are still reachable (e.g. because the DOM is reachable, or because you saved them in another data structure), you could fill metaspace.

  2. Behind the scenes, something into your application could be doing a lot of class loading. For example, if you make extensive use of dynamic proxies. That can put a lot of non-collectable classes into metaspace, ultimately filling it.

  3. It is possible that dynamic proxies (see previous point) are being created by the JAXBContext initialization. As a @PaulBastide noted, you should be able to create a single JAXBContext and reuse it. As well as being more efficient, doing that could solve a metaspace leakage problem.

Increasing the size of metaspace is a band-aid solution. A better idea is to get the JVM to create a heap dump when it OOME's and analyze the dump to figure out what is using so much of metaspace. Then decide whether it is a problem you can address, or whether to use the -XX:MetaspaceSize=... band-aid and hope for the best.


This is rather late, but your problem causing java.lang.OutOfMemoryError: Map failed is not an ordinary memory leak; i.e. a leak of Java heap objects or native heap objects. It may not be a leak at all.

What is going on is that your code is trying the map a file into memory. The JVM asks the OS for a large memory segment to hold the file, and the OS says "no". There can be a number of reasons for this:

  1. The file you are trying to map may simply be too big.
  2. Your application may have already mapped lots of other files and failed to unmap them. (That would be a leak.)
  3. There may be a "ulimit" or similar restriction on your JVM process.
  4. If you are running a 32-bit JVM, you may have run up against the 32 bit virtual address space limit.

Upvotes: 2

Related Questions