【问题标题】:How to avoid OutOfMemoryError in Java?如何避免 Java 中的 OutOfMemoryError?
【发布时间】:2013-06-05 22:42:56
【问题描述】:

我是 Java 新手。我有这个 2 GB 的 xml 文件,我需要对其进行解析并将其数据存储到数据库中。

StackOverflow 上的某个人建议我使用 Dom4j 处理长 xml 文件。解析做得很好,但返回的文档(由 Dom4j)很长,并且在迭代时会将所有 DOM 对象加载到内存(堆)中。

这会导致内存不足异常。有人可以帮助我如何避免此类错误吗?我们在 Java 中是否存在一些 Java 中按需堆分配和沉积的现象?

【问题讨论】:

  • 是否可以选择 SAX 或 StAx?您需要内存中的所有数据吗?
  • 使用 stax 解析器,增加堆大小。
  • 最快的解决方案:使用更多内存运行您的 Java 应用程序(尝试使用 4 GB)。模式详细解决方案:不要将整个 XML 保存在内存中(因为它不适合),而是分块处理。

标签: java jakarta-ee


【解决方案1】:

如果您需要解析大型 XML 文件(并且添加到 Java 堆并不总是有效),您需要一个 SAX 解析器,它允许您解析 XML 流,而不是将整个 DOM 树加载到内存中。

您也可以查看SAXDOMIX

SAXDOMIX 包含可以转发 SAX 事件或 DOM 子树的类 在解析 XML 文档期间发送到您的应用程序。这 框架定义了允许应用程序获取的简单接口 SAX 解析中间的 DOM 子树。处理后,所有 DOM 子树有资格进行垃圾收集。这解决了 DOM 可扩展性问题。

【讨论】:

  • 感谢 Juned,我正在使用 Dom4j,我认为他们也有 SAX 解析器。正如其中一个代码 sn-p 所说 - SAXReader reader = new SAXReader();
  • 与 DOM 的问题是需要将整个 xml 树加载到内存中。无论你设置多大的堆大小,如果你的树不适合它,你最终会出现内存不足错误。 SAX 更适合解析大 xml,因为您可以分块读取。我喜欢 SAXDOMIX,因为它混合了 sax 和 dom,让你可以轻松地分块解析。试试看。
  • DOM(作为输出)被有意使用,因为许多 xml 节点是相互依赖的,并且完全 SAX 使处理变得非常缓慢。 Dom4j 中的 SAX 解析器不做同样的工作吗?
【解决方案2】:

你有两个选择:

  1. 重新配置 JVM 以分配更多最大内存(通过 -Xmx2g 或类似方法)。见here for more info。此选项显然还受到您的操作系统和系统中可用内存量的限制。
  2. 使用流式传输 API(例如SAX),它不会一次将所有 XML 加载到您的内存中,而是将其流式传输到您的进程中,让您无需等待即可对其进行分析内存中的整个文档

第一个选项可能会立即为您提供帮助,并且并非针对此问题。第二个选项是更具可扩展性的解决方案,因为它允许您分析任何大小的文档。当然,您需要担心分析结果的内存消耗,但这完全是另一回事。

【讨论】:

  • 谢谢布赖恩,我当然知道增加堆大小,分块处理 XML 是个好建议。但是我需要一些通用的解决方案来避免在堆中加载过多的数据。大表也存在相关问题 - 大约有 15000 条记录。也有人说要使用游标。但这些解决方案似乎是上下文相关的——是否有任何通用的解决方案或指南来避免内存不足的异常情况? Dom4j 也有一个 SAX 解析器。
猜你喜欢
  • 2017-03-20
  • 1970-01-01
  • 2018-01-11
  • 2011-07-14
  • 1970-01-01
  • 1970-01-01
  • 2017-11-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多