Javaで最大500MBのXMLファイルを解析しようとしています。SAXを使用しようとしましたが、このエラーが発生しますjava.lang.OutOfMemoryError:com.sun.org.apache.xerces.internal.util.XMLStringBuffer.append(Unknown Source)のJavaヒープスペース助けてくれませんか?どうもありがとう。PS小さいXMLファイルは問題なく機能します
7 に答える
SAX を正しく使用していないか、アプリケーションがストリーム処理に適していない可能性があります。
SAX の要点は、XML 構造全体をメモリに保持しないようにすることですが、これが可能なのは、多くのコンテキストを保持せずに XML を小さなチャンクで処理できる場合と、処理の結果が処理された XML よりもはるかに小さい場合 (あまりにも多くのメモリを使用しないようにするため)、またはそれ自体を受信者に渡すか、継続的にディスクに書き込むことができます。
編集:単にメモリ リークが発生している可能性もあります。つまり、もう必要のないデータを保持しているために、ガベージ コレクションが妨げられている可能性があります。XML の処理にリスト、マップ、またはセットを使用する場合は、XML の 1 つのチャンクの処理中にそれらに追加したものは、次のチャンクを開始する前に削除されていることを確認してください。
StAX for Java バージョン 6 より前: http://stax.codehaus.org/
非常に大きな XML ファイルを解析できる ScaleDOM をチェックしてみてください: https://github.com/whummer/scaleDOM
ScaleDOM は、XML ノードの遅延読み込みにより、メモリ フットプリントが小さくなります。XML ドキュメントの一部のみがメモリに保持され、必要に応じてソース ファイルからノードが再ロードされます。
次の 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>
そして、すべての <item> を取得したい
public class Item
{
String name;
String age;
}
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);
}
}
}
ご覧のとおり、はとタグcontent
の間でのみ記憶されます。age
name
Apache Digester を見てください。