如何在没有堆错误的情况下将大型 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
。
目前我正在使用 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
。