Big XML文件和OutOfMemoryError

时间:2009-02-02 20:15:00

标签: java xml memory parsing out-of-memory

我正在尝试在java中解析高达500 MB的XML文件。我试图使用SAX,但它给了我这个错误 java.lang.OutOfMemoryError:Java堆空间        at com.sun.org.apache.xerces.internal.util.XMLStringBuffer.append(Unknown Source) 你能帮助我吗? 非常感谢。 附:较小的XML文件可以正常工作

7 个答案:

答案 0 :(得分:11)

您很可能没有正确使用SAX,或者您的应用程序不适合流处理。

SAX的重点是避免将整个XML结构保留在内存中,但只有在不保留大量上下文的情况下才能以小块的形式处理XML,并且处理结果要小于已处理的XML(因此它不会使用太多内存)或者本身可以传递给收件人或连续写入磁盘。

编辑:您也可能只是内存泄漏,即您正在查看不再需要的数据,从而阻止其收集垃圾。如果您使用任何列表,地图或集来处理XML,请确保在开始下一个块之前删除处理一个XML块时添加的任何内容。

答案 1 :(得分:5)

尝试使用Streaming API for XML(java6中的新增功能) 它为此做了

http://www.javabeat.net/articles/14-java-60-features-part-2-pluggable-annotation-proce-2.html

答案 2 :(得分:3)

您可以通过指定例如

来尝试增加Java堆大小
java -Xmx1024M MyClass
命令行上的

(或任何值适合您的文档大小)。

答案 3 :(得分:2)

StAX for Java版本6之前版本: http://stax.codehaus.org/

答案 4 :(得分:1)

假设您有以下XML结构:

<?xml version="1.0"?>
<list>
  <item>
    <name>Alpha</name>
    <age>10</age>
  </item>
  <item>
    <name>Beta</name>
    <age>20</age>
  </item>
  <!-- many many items -->
</list>

并且您希望获得所有&lt; item&gt; s

公共类项目      {      字符串名称;      字符串年龄;      }

您的SAX处理程序将如下所示

public class MyHandler extends DefaultHandler
{
 Item current=null;
 StringBuilder content=null;
 @Override
    public void startElement(String uri, String localName, String name,
                    Attributes attributes) throws SAXException {
            if(     name.equals("item")
                  {
                  current= new Item();
                  }
            else if(name.equals("name") || name.equals("age"))
                  {
                  content= new StringBuilder();
                  }
            }

     @Override
    public void endElement(String uri, String localName, String name)
                    throws SAXException
            {
            if(name.equals("item"))
                    {
                   //DO SOMETHING WITH current
                    System.out.println(current);
                    current=null;
                    }
             else if(name.equals("name"))
                    {
                    current.name= content.toString();
                    }
             else if(name.equals("age"))
                    {
                    current.age= content.toString();
                    }
             content=null;
             }

    @Override
    public void characters(char[] ch, int start, int length)
                    throws SAXException {
            if(content!=null)
                    {
                    content.append(ch,start,length);
                    }
            }

}

正如您所看到的,“内容”仅存储在“年龄”和“名称”标签之间。

答案 5 :(得分:1)

您可能需要查看ScaleDOM,它允许解析非常大的XML文件:https://github.com/whummer/scaleDOM

由于XML节点的延迟加载,ScaleDOM的内存占用量很小。它只将XML文档的一部分保留在内存中,并在必要时从源文件重新加载节点。

答案 6 :(得分:0)

看看Apache Digester。

Here is a small tutorial