JAXB - unmarshal OutOfMemory:Java堆空间

时间:2011-11-01 15:21:20

标签: java xml memory

我目前正在尝试使用JAXB解组XML文件,但似乎XML文件太大(~500mb)以供unmarshaller处理。我一直在java.lang.OutOfMemoryError: Java heap space @

Unmarshaller um = JAXBContext.newInstance("com.sample.xml");
Export e = (Export)um.unmarhsal(new File("SAMPLE.XML"));

我猜这是因为它试图将大型XML文件作为对象打开,但该文件对于Java堆空间来说太大了。

还有其他更多'内存有效'的方法来解析大型XML文件~500mb?或者也许是一个unmarshaller属性可以帮助我处理大型XML文件?

以下是我的XML的样子

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- -->
<Export xmlns="wwww.foo.com" xmlns:xsi="www.foo1.com" xsi:schemaLocation="www.foo2.com/.xsd">
<!--- --->
<Origin ID="foooo" />
<!---- ---->
<WorkSets>
   <WorkSet>
      <Work>
         .....
      <Work>
         ....
      <Work>
      .....
   </WorkSet>
   <WorkSet>
      ....
   </WorkSet>
</WorkSets>

我想在WorkSet级别解组,仍然能够阅读每个WorkSet的所有工作。

6 个答案:

答案 0 :(得分:10)

您的XML是什么样的?通常,对于大型文档,我建议人们使用StAX XMLStreamReader,以便JAXB可以在块中对文档进行解组。

<强> input.xml中

在下面的文档中,有许多person元素的实例。我们可以使用带有StAX XMLStreamReader的JAXB来一次解组相应的Person个对象,以避免内存不足。

<people>
   <person>
       <name>Jane Doe</name>
       <address>
           ...
       </address>
   </person>
   <person>
       <name>John Smith</name>
       <address>
           ...
       </address>
   </person>
   ....
</people>

<强>演示

import java.io.*;
import javax.xml.stream.*;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception  {
        XMLInputFactory xif = XMLInputFactory.newInstance();
        XMLStreamReader xsr = xif.createXMLStreamReader(new FileReader("input.xml"));
        xsr.nextTag(); // Advance to statements element

        JAXBContext jc = JAXBContext.newInstance(Person.class);
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        while(xsr.nextTag() == XMLStreamConstants.START_ELEMENT) {
            Person person = (Person) unmarshaller.unmarshal(xsr);
        }
    }

}

<强>人

我们需要在我们将解组的XML片段的本地根目录上添加@XmlRootElement注释,而不是匹配XML文档的根元素。

@XmlRootElement
public class Person {
}

答案 1 :(得分:5)

您可以使用-Xmx启动参数来增加堆空间。

对于大型文件,SAX处理因为事件驱动而具有更高的内存效率,并且不会将整个结构加载到内存中。

答案 2 :(得分:2)

我一直在做很多研究,特别是在解析非常大的输入集方面。确实,您可以将StaX和JaxB组合在一起以选择性地解析XML片段,但这并不总是可行或更可取。如果您有兴趣阅读有关该主题的更多信息,请查看:

http://xml2java.net/documents/XMLParserTechnologyForProcessingHugeXMLfiles.pdf

在本文档中,我描述了一种非常简单易用的替代方法。它解析任意大的输入集,同时让您以javabeans的方式访问您的数据。

答案 3 :(得分:1)

使用SAXStAX。但如果目标是拥有文件的内存中对象表示,那么仍然需要大量内存来保存这样一个大文件的内容。在这种情况下,您唯一的希望是使用-Xmx1024m JVM选项(将最大堆大小设置为1024 MB)来增加堆大小。

答案 4 :(得分:0)

SAX但您必须自己构建Export对象

答案 5 :(得分:0)

你也可以尝试这种做法,这是一种不好的做法 但它的工作:)谁关心

http://amitsavm.blogspot.in/2015/02/partially-parsing-xml-using-jaxb-by.html

其他明智的使用STAX或SAX或者Blaise Doughan所说的也很好,你可以说一种标准的方式,但是如果你有复杂的XML结构并且你不想手动注释你的类并使用XJC工具。

在这种情况下,这可能会有所帮助。