我一直在使用SAX解析器一段时间来从各种XML中获取数据,但今天我正在用一个简单的XML(与以前的那些相比,这里大约12k行)的新问题。其中有很多重复的项目。大多数情况下,这些项目都是一个块的一部分:
<content>
<item lbl="blabla">
<item lbl="blabla"/>
<item lbl="blabla"/>
</item>
<item lbl="blabla">
<item lbl="blabla"/>
<item lbl="blabla"/>
<item lbl="blabla"/>
<item lbl="blabla"/>
<item lbl="blabla"/>
<item lbl="blabla"/>
</item>
</content>
blabla部分当然正在改变......但是,我想保留项目的结构(它们是标题和副标题)。为此,我将每个blabla附加一个起始和结束标记<itemx>blabla</itemx>
,其中x是项目树(1,2,3或4)中的位置。
稍微有问题的部分是,我正在创建成千上万的无用对象,垃圾收集器没有时间在解析器之后进行清理,并且不可避免的OutOfMemory出现在我面前......
我不知道如何处理它;最好的技术是如果我可以获取<content></content>
的全部内容,但我不确定这是否可以使用SAX解析器。
欢迎任何帮助,任何解决方案都深深感谢...
答案 0 :(得分:3)
如果您尝试阅读的数据超出可用内存,则您需要保留数据以释放内存以继续阅读。
您是否考虑过在阅读时将数据存储在sqlite database中?
您还应该避免创建大量无用的临时对象,是否可以通过改变单个对象或小对象池来避免垃圾堆积?
如果您希望将整个文档树放在内存中,那么您应该使用DOM解析器(Android上可以使用DocumentBuilder
)。但是,如果您使用的是内存不足SAX解析器,DOM解析器很可能也会耗尽,除非你的SAX事件正在制造和销毁大量的对象实例。
答案 1 :(得分:2)
在大多数情况下,您无法“足够快地创建对象以至于GC无法跟上”。实际上,当GC需要发生时,整个应用程序都会暂停,直到完成为止,所以你无法超越它。
唯一的例外是Bitmaps,它们有点特殊处理 - 它们计入Java堆,即使它们的分配没有发生在它上面。这很好,除非Bitmap的内存在其终结器运行之前不会被释放,终结器执行与收集的垃圾分开运行并且不会阻止应用程序。因此,创建一堆位图并简单地放弃它们(不调用方法来显式释放Bitmap的内存)确实会导致内存不足异常。
但是如果你没有分配(和放弃)Bitmap对象,你还有其他问题,可能只是......没有足够的内存用于所有的分配。您可以使用hat工具(在较小程度上使用DDMS中的简单Java堆信息)来查看使用了大量空间的已分配内容。