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

How to marshall large java objects to xml without heap error?

目前我正在使用 JAXB 编组器来编组大型 java 对象并且它正在工作但是当我收到大型 java 对象应用程序时抛出 OutOfMemoryError: heap space 错误.

谁能告诉我如何将大型 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)

我会给你简短和长的答案。

简短(实用)回答

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

更长的答案

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

顺便说一句:确保在序列化对象时将其直接编组到文件(或网络资源或其他外部目标),而不是字节数组或字符串。

编辑

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