目前我正在使用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)
答案 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
。