我目前正在尝试使用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的所有工作。
答案 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)
使用SAX或StAX。但如果目标是拥有文件的内存中对象表示,那么仍然需要大量内存来保存这样一个大文件的内容。在这种情况下,您唯一的希望是使用-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工具。
在这种情况下,这可能会有所帮助。