gpt4 book ai didi

java - JDOM 正在使用太多内存

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:43:25 25 4
gpt4 key购买 nike

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

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

我已经尝试使用 SlimJDOMFactory,但仍然占用了过多的内存!!

实际上我需要在 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");
}
}

最佳答案

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

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

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

这个问题的典型解决方案是:

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

这些解决方案都不是“好”的,但这就是您使用内存中 XML 系统所获得的。

关于java - JDOM 正在使用太多内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23828671/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com