【问题标题】:Exception for no memory while parsing large XML file in SAX parser在 SAX 解析器中解析大型 XML 文件时没有内存的异常
【发布时间】:2015-06-07 20:54:22
【问题描述】:

我已经阅读了一些关于使用 SAX 解析器在 java 中解析 XML 文件优于使用 DOM 的优势的文章。 最吸引我的一个(如here 所讨论的)是

Sax 适用于大型 XML 文件,SAX 解析器不会将 XML 文件作为一个整体加载到内存中。

但现在我已经编写了一个解析器,使用 SAX 从 XML 文件中为一个几乎 1.4 GB 的大文件派生实体,它会生成以下异常。

org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; The parser has encountered more than "64,000" entity expansions in this document; this is the limit imposed by the application.

如果整个文件没有加载到内存中,内存有什么问题。

我该如何解决这个问题?

【问题讨论】:

  • 这不一定是实际的内存限制,而是针对像 this one 这样的 DOS 攻击的保护措施。如果您的输入 XML 合法包含那么多实体,您可以在解析器中增加该限制。查看它的文档。
  • 你建议我用这个保护措施做什么?
  • 我以为我是这么说的。
  • 我应该看一下JVM的文档吗?

标签: java xml parsing


【解决方案1】:

您也可以考虑使用 StAX。

SAX 是事件驱动和串行的。它可以处理大型 XML,但会占用大量 CPU 资源。

DOM 正在内存中获取完整的文档。

StAX 是更新的 API。它通过 XML 流式传输。它可以看作是文档上的游标或迭代器。它的优点是可以跳过不需要的元素(属性、标签等)。如果使用得当,它占用的 CPU 资源会少很多。

https://docs.oracle.com/javase/tutorial/jaxp/stax/why.html

使用 SAX,XML 推送事件。

使用 StAX,您可以将 XML 拉给您。

【讨论】:

  • 这是否意味着我为创建一个实际上适用于较小文件的解析器(使用 SAX)所做的所有努力都白费了?
  • 没有。如果您解决了问题,您可以坚持使用 SAX。我只是想告诉您,还有另一种解析 XML 的现代方式。另一个优点:使用 SAX 只能解析 XML,使用 StAX 也可以编写 XML。
  • 如果您已经使用精心挑选的方法编写了 SAX 实现,也许您可​​以重用大量代码并尝试使用 StAX 方法来衡量性能差异。相信我,你会感到惊讶:正确使用并跳过不必要的元素,你的解析时间会大大减少!
  • 在对下面答案的评论中,我为我的代码添加了一个链接。你看。
  • 这只是一个建议!如果你愿意,我可以为你提供一个 StAX sn-p。它通常以某种模式使用。我会查一下,并用一个小例子编辑我的帖子。
【解决方案2】:

使用 JVM 参数更改实体扩展限制:

-DentityExpansionLimit=1000000

【讨论】:

  • 取决于您运行程序的方式。这是一个命令行参数。
  • 这篇文章stackoverflow.com/questions/29360901/… 包含我的解析器代码希望你明白我是如何处理它的
  • 是的,但是你是如何运行它的。你是在命令提示符下输入 java blah blah 吗?您是通过 IDE 执行它吗?
  • 在参数选项卡上的运行配置下,它被称为“VM 参数”。这就是您要添加的地方。
  • 非常感谢您的帮助。 :) 我真的很满足你。
猜你喜欢
  • 1970-01-01
  • 2012-05-23
  • 2011-08-06
  • 2020-03-28
  • 1970-01-01
  • 1970-01-01
  • 2016-03-24
  • 1970-01-01
  • 2012-08-27
相关资源
最近更新 更多