如何在没有堆错误的情况下将大型java对象编组为xml?

时间:2015-05-04 08:09:34

标签: java xml jaxb marshalling

目前我正在使用JAXB marshaller来编组大型java对象并且它正在工作但是当我回忆起大型java对象应用程序时抛出了OutOfMemoryError:堆空间错误。

有人可以让我知道如何将大型java对象编组到xml而不会出现堆错误。

StringWriter writer = new StringWriter();
JAXBContext.newInstance("packageName").createMarshaller.marshall(myObject,writer);
return writer.toString();

这是确切的堆栈错误,

Caused by: java.lang.OutOfMemoryError: Java heap space
    at java.lang.StringBuffer.ensureCapacityImpl(StringBuffer.java:338)
    at java.lang.StringBuffer.append(StringBuffer.java:114)
    at java.io.StringWriter.write(StringWriter.java:88)
    at java.io.BufferedWriter.flushBuffer(BufferedWriter.java:122)
    at java.io.BufferedWriter.flush(BufferedWriter.java:246)
    at com.ibm.jtc.jax.xml.bind.v2.runtime.MarshallerImpl.cleanUp(MarshallerImpl.java:339)
    at com.ibm.jtc.jax.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:332)
    at com.ibm.jtc.jax.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:249)
    at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:95)
    at com.ibm.xml.xlxp2.jaxb.marshal.MarshallerImpl.marshal(MarshallerImpl.java:210)
    at com.mine.app.util.AppUtility.marshalXMLPayload(Unknown Source)

1 个答案:

答案 0 :(得分:4)

我会给你一个简短的答案。

简短(实用)答案

你有20个对象,每个对象15Mb。这意味着它们占用约300Mb。可能XML表示占用了两倍。因此,将JVM堆配置为1 - 2 G并忘记继续开发。 (运行JVM时使用-Xmx1G)命令行选项。

更长的答案

OOM为什么会发生?您可以使用使用DOM的JAXB将对象序列化为XML。这意味着首先系统会创建巨大对象的DOM表示,然后将其序列化为文本形式。所有这些都需要大量的内存。 您可以避免使用JAXB并找到将对象序列化为XML或编写自己的代码的其他工具。我不确定,但试试XStream。它是一个非常强大的工具,并且至少能够使用SAXt进行解析,所以它可能知道也可以递增地序列化对象。 该解决方案比第一个解决方案更具可扩展性,但需要编码。

BTW:确保在序列化对象时直接将其编组到文件(或Web资源或其他外部目标)而不是字节数组或字符串。

修改

您对问题的最新补充证明了我的恐惧。 你的问题不是在JAXB序列化中,而是在创建巨大的字符串。你为什么做这个?我怀疑你将它存储在RAM中以备将来使用。我相信你马上把它写到一些流(文件,网络,无论什么 - 无关紧要。)这意味着你实际上根本不应该创建字符串。不要使用StringWriter然后使用StringWriter.toString()(抛出异常的地方)。如果要将XML直接写入文件,请使用FileWriter