- PR -

XMLパースで発生するjava.lang.OutOfMemoryErrorの回避方法

投稿者投稿内容
はまさん
常連さん
会議室デビュー日: 2004/12/07
投稿数: 20
投稿日時: 2005-03-10 16:29
こんにちは。はまのっぷーと申します。

ファイルサイズの大きいXMLファイルをパースすると、
java.lang.OutOfMemoryErrorが発生するのですが、
これを回避する方法が分かりません。
もちろん動作環境の整備を行うことが前提ですが、どんなにメモリを積んでも
いずれはjava.lang.OutOfMemoryErrorが発生すると思っています。

どなたか回避案を頂けませんでしょうか。

ちなみにソースコードは以下のとおりです。
XMLファイルをパースするのみです。
コード:
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
import org.w3c.dom.*;

public class DomTest {
  
  public static void main(String[] args) {
    String fileName = args[0];

    try {
      DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();
      DocumentBuilder builder = dbfactory.newDocumentBuilder();
      Document d = builder.parse(fileName);
      
      System.out.println("Normal End.");
    
    } catch(Exception e) {
      e.printStackTrace();
    }
  }
}

uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2005-03-10 16:40
まず現象をとりあえず回避するだけなら、-Xms、-Xmxオプションの指定によってVMのメモリ
サイズを増やすことで対処できると思います。次にサイズによらずメモリ不足を回避する
手段ですが、パースの目的にもよりますがDOMではなくSAXを使うことで回避できないでしょうか。
はまさん
常連さん
会議室デビュー日: 2004/12/07
投稿数: 20
投稿日時: 2005-03-10 17:07
ご回答ありがとうございます。

NodeListやElementといったツリー構造でデータ操作を行いたいので、
SAXは考えていませんでした。

ただ、オラクルのDOM Parserのように
一度SAXでパースしてDOMツリーに詰めなおせばメモリ不足は発生しないのですかね。。。
以下を参考にしました。
http://www.atmarkit.co.jp/fxml/rensai/xdk03/xdk03.html

もし他の案があればご教授お願いいたします。。
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2005-03-10 17:22
限りがあるヒープ領域ですので、ドキュメントのサイズが大きければ必ず OutOfMemoryError は発生します。
DOM はすべてメモリ上に読み込んで操作を行う API ですから。

SAX の場合ノードを一つ一つ追っていって必要のない要素、属性はどんどんガベージコレクトの対象になるのでしてしまえば良いのでどんなにドキュメントのサイズが大きくても OutOfMemoryError は発生しません。
はまさん
常連さん
会議室デビュー日: 2004/12/07
投稿数: 20
投稿日時: 2005-03-10 17:31
やはりDOMでは限界があるということなのですね。。

ただ、XMLパースした結果をメモリ上で保持する予定ですので、SAXは使えず。。
java.lang.OutOfMemoryErrorが出た時点で何らかのアクションを起こすことで逃げたいと思います。

ご回答ありがとうございました
シュン
ぬし
会議室デビュー日: 2004/01/06
投稿数: 328
お住まい・勤務地: 東京都
投稿日時: 2005-03-10 18:21
http://www-6.ibm.com/jp/developerworks/xml/030530/j_x-tipbigdoc.html

SunJRE標準のDOM APIより、メモリフットプリントの小さいDOM API実装がいくつ
かあるようですよ。試してみてはいかがでしょうか。
Gio
ぬし
会議室デビュー日: 2003/11/28
投稿数: 350
お住まい・勤務地: 都内から横浜の間に少量発生中
投稿日時: 2005-03-10 18:22
全然参考にはならないと思いますが、ドキュメント情報をすべてメモリ上に保持する方法は DOM だけに限りません。
SAX でパーズした結果を受けて独自のモデルを構築する方法もあります。
ただし、自前でモデルを設計・実装する必要がありますが。
Sun の JAXB というものも使えると思いますが、こちらはスケジュールが捗々しくないようです。

エレメントやアトリビュートの情報を保持する方法としては DOM はメモリ消費量が大きいので、それだけの必要性がありコストが割ける場合のみ、独自モデルも検討されるとよろしいと思います。

# やたら大きかったり構造が複雑なファイルでの動作は保証しないというのも、仕様の一項目としては正当でしょう。

最後に蛇足ですが、処理対象としない部分をノード展開せずに圧縮した形式で保持してメモリ消費量を削減するという、富士通が発表した SPlitDOM (http://xml.fujitsu.com/jp/tech/split/) という技術があります。
ご参考まで。
はまさん
常連さん
会議室デビュー日: 2004/12/07
投稿数: 20
投稿日時: 2005-03-10 18:48
色々とアドバイスありがとうございます。
是非参考にさせていただきます。

スキルアップ/キャリアアップ(JOB@IT)