我们使用XStream对XML进行序列化/反序列化......并且只获得了OutOfMemory
异常。
首先,我不明白为什么我们收到错误,因为我们已经为服务器分配了500MB。
问题是 - 我们应该做出哪些改变以避免麻烦?我们希望确保此实施规模。
目前我们有~60K个对象,每个~50个字节。我们在内存中加载60K POJO,并将它们序列化为一个String,我们使用HttpClient
发送给Web服务。接收时,我们获取整个String,然后转换为POJO。 XML /对象层次结构如下:
<root>
<meta>
<date>10/10/2009</date>
<type>abc</type>
</meta>
<data>
<field>x</field>
</data>
[thousands of <data>]
</root>
我收集最好的方法是不将POJO存储在内存中,不将内容写入单个String。相反,我们应该将单个<data>
POJO写入流。 XStream supports这似乎不支持<meta>
元素。数据需要采用以下形式:
<root>
<data>
<field>x</field>
</data>
[thousands of <data>]
</root>
那么什么方法最容易流式传输整个树?
答案 0 :(得分:3)
您肯定希望避免将POJO序列化为庞大的字符串,然后将该字符串写出来。使用XStream API将POJO直接序列化到OutputStream。今年早些时候,当我发现我生成200-300Mb的XML文档并获得OutOfMemoryErrors时,我遇到了同样的情况。切换非常容易。
当然对于阅读方而言同样如此。不要将XML读入String并要求XStream从该String反序列化:直接从InputStream反序列化。
您提到了第二个问题,即无法序列化<meta>
元素和<data>
元素。我不认为这是一个XStream问题或限制因为我按照以下顺序常规地序列化更复杂的结构:
<myobject>
<item>foo</item>
<anotheritem>foo</anotheritem>
<alist>
<alistitem>
<value1>v1</value1>
<value2>v2</value2>
<value3>v3</value3>
...
</alistitem>
...
<alistitem>
<value1>v1</value1>
<value2>v2</value2>
<value3>v3</value3>
...
</alistitem>
</alist>
<anotherlist>
<anotherlistitem>
<valA>A</valA>
<valB>B</valB>
<valC>C</valC>
...
</anotherlistitem>
...
</anotherlist>
</myobject>
我也成功地对嵌套列表进行了序列化和反序列化。
答案 1 :(得分:2)
不确定这里的问题是什么......你在那个网页上找到了答案。
您提供的链接上的示例代码建议:
Writer someWriter = new FileWriter("filename.xml");
ObjectOutputStream out = xstream.createObjectOutputStream(someWriter, "root");
out.writeObject(dataObject);
// iterate over your objects...
out.close();
并且阅读几乎完全相同但是使用Reader for Writer和Input for Output:
Reader someReader = new FileReader("filename.xml");
ObjectInputStream in = xstream.createObjectInputStream(someReader);
DataObject foo = (DataObject)in.readObject();
// do some stuff here while there's more objects...
in.close();
答案 2 :(得分:0)
我建议使用Visual VM或Eclipse Memory Analyzer等工具来确保您没有内存泄漏/问题。
另外,你怎么知道每个对象是50个字节?这听起来不太可能。
答案 3 :(得分:0)
使用XMLStreamWriter(或XStream)对其进行序列化,您可以在其上编写任何内容。如果您可以选择获取输入流而不是整个字符串,请使用SAXParser,它是基于事件的,虽然实现可能有点笨拙,但您将能够读取任何抛出的XML,甚至如果XML很大(我用SAXParser解析了2GB以上的XML文件)。
正如旁注,您应该将二进制数据而不是字符串发送到XML解析器。 XML解析器将读取将在XML序列的开头通过xml标记接下来的字节数组的编码:
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
字符串已经被编码。最好让XML在使用它创建String之前解析原始流。