【问题标题】:Java heap space when adding documents to List of documents将文档添加到文档列表时的 Java 堆空间
【发布时间】:2014-01-18 00:22:46
【问题描述】:

我正在使用 import org.w3c.dom.Document;用于文档。

我有这段代码从arraylist fileList解析xml文件,有2000多个xml文件要解析,xml文件的大小约为30-50 Kb,我解析文件没有问题:

    try {
        for(int i = 0; i < fileList.size(); i++) {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(fileList.get(i)); //<------ error will point here when docList.add(doc) is uncommented.
            docList.add(doc); 
        }
    } catch (ParserConfigurationException | SAXException | IOException e) {
        e.printStackTrace();
    }

但每当我将它们添加到列表中时,就会出现此错误:

线程“主”java.lang.OutOfMemoryError 中的异常:Java 堆空间 在 com.sun.org.apache.xerces.internal.dom.DeferredDocumentImpl.createChunk(未知来源) 在 com.sun.org.apache.xerces.internal.dom.DeferredDocumentImpl.ensureCapacity(未知来源) 在 com.sun.org.apache.xerces.internal.dom.DeferredDocumentImpl.createNode(未知来源) 在 com.sun.org.apache.xerces.internal.dom.DeferredDocumentImpl.createDeferredTextNode(未知来源) 在 com.sun.org.apache.xerces.internal.parsers.AbstractDOMParser.characters(未知来源) 在 com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(未知来源) 在 com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(未知来源) 在 com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(未知来源) 在 com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(未知来源) 在 com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(未知来源) 在 com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(未知来源) 在 javax.xml.parsers.DocumentBuilder.parse(未知来源) 在 com.test.parser.Parser.getDocs(Parser.java:146) 在 com.test.parser.Parser.main(Parser.java:50)

取消注释 docList.add(doc) 不会产生此异常,知道为什么会发生这种情况吗?

编辑:我在 Run Configurations 中将 -Xmx1024M 添加到 VMArguments 并且它有效。

【问题讨论】:

  • 为什么每次循环都创建新的实例?
  • 相当粗略的估计表明您将需要大约 140 MB 的 RAM。增加 Java 堆大小:-Xmx400M
  • @csmckelvey,我只是在试验代码,因为我得到了这个错误,我在 for 循环之外有一个不同的 DocumentBuilder。
  • 我不会基于增加堆大小来制定任何解决方案,除非我真的必须这样做。 fileList.size() 总是可能更大,所以这没有意义。

标签: java xml out-of-memory


【解决方案1】:

uncommenting the docList.add(doc) does not produce this exception, any idea why this is happening?

很简单:如果不将doc 引用存储在docList 中,文档引用将被新对象-Document doc = builder.parse(fileList.get(i)); 覆盖,因此之前迭代中的doc 将是孤儿-没有引用的对象。这会被 JVM 垃圾收集器快速删除,因此在循环期间,堆上最多有 2 个 doc 对象。

但是,当docList.add(doc) 处于活动状态时,您仍然可以引用循环中创建的所有文档对象:正是fileList.size() 实例。它们不会被垃圾收集器收集(并从堆中删除),因为docList 将拥有对它们的有效、活动引用。

如何避免OutOfMemoryError?只需在销毁前一个文档的 DOM 对象后,逐个解析/处理文档,或考虑使用流式解析器,例如SAXParser

【讨论】:

    【解决方案2】:

    右键单击项目文件夹 点击 -> runAs -> 运行配置 -> 点击参数选项卡 -> 添加

    -xmx512M 按回车 -xmx2048M

    应用并运行。

    【讨论】:

    • 欢迎来到 StackOverflow!这个原始问题没有提到任何特定的 IDE,所以如果没有更多信息,这个建议就无法付诸实施。同样,这并不能回答 OP 的问题,该问题与异常的原因有关,而不是如何可能减轻它。这篇文章最好作为评论留在主帖下方,或者完全删除。
    猜你喜欢
    • 1970-01-01
    • 2013-11-30
    • 2014-04-01
    • 2011-01-02
    • 2017-11-25
    • 2021-12-19
    • 1970-01-01
    • 2012-06-23
    • 2010-10-27
    相关资源
    最近更新 更多