JDOM使用太多内存

JajaDrinker:

我有一个使用XmlUnit从两个XML文件中获取差异的应用程序。但是问题是XmlUnit使用JDOM。我的xml文件很大〜1GB!

将这些xml存储在JDOM文档中需要太多RAM。

我尝试使用SlimJDOMFactory,但仍然使用过多的RAM!

实际上,我需要在XML文件中前后导航。没有JDOM,我找不到简单的方法。

有人可以帮忙吗?

这是有关如何构建JDOM文档的代码示例:

    private org.jdom2.Document refDocJdom2;
    private org.jdom2.Document resDocJdom2;
    SAXBuilder sxb = new SAXBuilder(); 
    sxb.setJDOMFactory(new SlimJDOMFactory());

    popmsg("Validating reference file...");
    try {
        refDocJdom2 = sxb.build(referenceXML_Path); 
    } catch (Exception e) { 
        JOptionPane.showMessageDialog(null, "Error while parsing   Reference : "+referenceXML_Path+" file.\nCheck XML file validity.");
        return;
    }
    popmsg("Reference file validated");

    popmsg("Validating result file....");
    try {
        resDocJdom2 = sxb.build(resultXML_Path); 
    } catch (Exception e) { 
        JOptionPane.showMessageDialog(null, "Error while parsing result "+resultXML_Path+" file.\nCheck XML file validity.");
        return;
    }
    popmsg("Result file validated");
    popmsg("Validation Done.");

    getDifferencies(referenceXML_Path, resultXML_Path);
    d2 = new Date();

  }
public void getDifferencies(String fileRef, String fileRes) throws SAXException, IOException {
    popmsg("Documents : VALID XML format");
    popmsg("Shearching for differencies....");

    Reader refReader;

    refReader = new FileReader(fileRef);
    Reader resReader = new FileReader(fileRes);
    Diff aDifference = new Diff(refReader, resReader);

    if(refReader != null){
        refReader.close();
    }
    refReader = null;

    if(resReader != null){
        resReader.close();
    }
    resReader = null;

    //TODO
     //     XMLUnit.setIgnoreWhitespace(true);

    myDetailledDiff = new DetailedDiff(aDifference);
    myDetailledDiff.overrideDifferenceListener(new IgnoreNamedElementsDifferenceListener());
    myDetailledDiff.overrideElementQualifier(new ElementNameAndAttributeQualifier()); 
    allDiffs = myDetailledDiff.getAllDifferences();
    myDetailledDiff = null;

    popmsg("Got all differencies...\nGoing to Sort them now...");

    popmsg("Diff SIZE : "+allDiffs.size());
    myDiffsList = new ArrayList<MyDifference>(allDiffs.size());
    if(allDiffs.size() > 0){
        Difference aDiff;
        for (int i = 0; i < allDiffs.size(); i++){
            aDiff =  (Difference) allDiffs.get(i);

            myDiffsList.add(new MyDifference(aDiff, refDocJdom2, resDocJdom2));

            if(myDiffsList.size() == LIMIT)
                return ;
            if (i%25 == 0 && i!= 0){
                popmsg("**************************************************\t"+i+"\n");
            }
        }

        allDiffs.clear();
        allDiffs = null;

    }else{
        popmsg("NO DIFERENCIES");
    }
}
rolfl:

JDOM将整个XML文档读入内存。对于任何基于内存的XML模型(XOM / DOM / JDOM / etc。),这都是“正常的”。这也是这些系统的众所周知的弱点。最终,在保留整个XML的内存内表示的同时,没有解决此问题的方法。

读取XML文档(通常为UTF-8)时,磁盘上1GB的数据通常会按比例转换为内存中的这么多字符,大约为2GB。那就是您应该为1GB XML文档“预算”的内容。

SlimJDOMFactory重用XML内的字符串,而不是保留对新字符串的引用,从本质上讲,它对字符串值进行重复数据删除。当您有许多具有相同名称的元素,标签和其他结构时,这非常方便。例如,如果没有SlimJDOMFactory,则具有1M个<tag />元素的XML文档将具有1M个不同的Element实例,每个实例都有自己的name tag假设tag是大约32Byte的对象,那么将需要大约32MB来存储这些字符串。SlimJDOMFactory会将其减少到仅32Bytes,但是,这只是“到目前为止”,它不能解决以下事实:随着文档的增长,它将占用更多的空间.....它在运行时只是“延迟”记不清。它还有其他一些后果,包括好的和坏的。。。。:好的,它减少了垃圾回收时间,因为用于扫描的内存更少,由于它消除了重复数据,它(略微)减慢了文档的加载时间。我的测试表明,对于即使在内存中驻留了几个GC周期的文档,也可以迅速实现较小的内存占用的净收益,并且解析方面的性能成本可以“收回”。

此问题的典型解决方案是:

  1. 直接使用SAX-完全没有内存模型...
  2. 将输入文件分成较小的块。这是正常的解决方案,出于多种原因(在减少延迟,可以并行解析文件等方面),这很有意义。
  3. 在逻辑上将XML划分为仍然是有效XML的部分,并使用文件子集上的特殊InputStreams解析文件的各个部分。
  4. 向系统添加更多内存。
  5. 使用自定义的JDOMFactory跳过您将不再需要的内容(JDOMFactory作为文档SAXBuild流程的一部分被调用...因此,您实际上可以将文件内容“修剪”到仅知道您需要的子集。 ....仍然以内存中的JDOM文档和可导航的(最后剩下的)结尾。

这些解决方案都不是“绝佳”的,但这就是内存XML系统所能提供的。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章