【问题标题】:getting heap space out of memory error- how is java heap memory used使堆空间超出内存错误-如何使用 Java 堆内存
【发布时间】:2012-12-13 22:02:42
【问题描述】:

我正在读取一个大小为 2.6GB 的 XML 文件——JVM 的大小为 6GB。

但是我仍然收到 Heap Space out of memory 错误?

我在这里做错了什么......

作为参考,我输出了JVM的最大内存和空闲内存属性--

最大内存显示为大约 5.6GB,但可用内存显示为只有 90MB...为什么只有 90MB 显示为空闲,尤其是。当我什至还没有开始任何处理时......我刚刚启动了程序?

【问题讨论】:

  • 您使用的是什么操作系统?有些对一个进程可以消耗多少内存有限制……我相信 32 位窗口最大为 2gb。
  • 2.6GB XML - 天哪!使用数据库!!由于所有节点对象、子列表、属性对象等,将 XML 文件存储在内存中将比磁盘上的平面文件使用更多的空间。
  • @jlordo - 使用 SAX 或 DOM 读取 XML 文件可能是非常合适的做法。根据需求,数据库实际上可能是最差可能的解决方案。恕我直言...
  • @paulsm4 我同意,它可以完全合适。 2.6GB 的 XML 永远不适合 DOM 表示,并且仅在少数情况下适合 SAX。由于内存消耗、查询和操作机会以及访问速度,在这种数据量下,数据库是一个不错的选择。

标签: java memory-management memory-leaks heap-memory


【解决方案1】:

一般而言,在 Java 中将结构化文本转换为相应的数据结构时,您需要比输入文件的大小多出很多的空间。除了字符串所需的空间之外,还有很多与使用的各种数据结构相关的开销。

例如,每个String 实例有大约 32-40 字节的额外开销——更不用说每个字符存储在 两个 字节中,这实际上使 ASCII 的空间需求翻了一番——编码的 XML。

然后在将字符串存储在结构中时会产生额外的开销。例如,为了将 String 实例存储在 Map 中,您将需要大约 16-32 字节的额外开销,具体取决于实现和您测量使用情况的方式。

6GB 很可能不足以一次存储已解析的 2.6GB XML 文件...

底线:

如果您在内存中加载如此大的 XML 文件(例如,使用 DOM 解析器),您可能做错了什么。基于流的解析器(如 SAX)应该有更温和的要求。

或者考虑将 XML 文件转换为更可用的文件格式,例如嵌入式数据库 - 甚至是实际的基于服务器的数据库。这样您就可以毫无问题地处理更大的文档。

【讨论】:

  • +1 每个字节至少变成一个 16 位的字符,每个 String 是文件的每个部分,大约有 32 个字节的开销。
  • Here is an example 在 java 中读取 5MB XML 文件时使用 60MB 内存。
  • “6GB 很可能不足以一次存储已解析的 2.6GB XML 文件”。真的。但重点是 1)确保您运行的是 64 位 JVM(可以使用超过 2GB 的内存!),2) 使用 VisualVM(nee JConsole)之类的工具来准确分析正在使用大量内存,以及它的去向。恕我直言...
  • @paulsm4:考虑到典型的 DOM 解析器需要 4 倍于输入 XML 文件的大小,如果存在 2.6GB 文件,那么 4GB 文件的可能性不大以及大多数低端和中端服务器上可用的典型内存,我认为这种方法被设计破坏了,再多的配置、哄骗或祈祷也无法挽救它。
  • 哦,别忘了在内存中加载数据后,您仍然需要更多内存才能完成实际工作。 ..
【解决方案2】:

您应该避免一次将整个 xml 加载到内存中,而是使用可以处理大量 xml 的专用类。

【讨论】:

  • 当然。具体来说,是一个基于 SAX 的类,它只读取 XML 中直接感兴趣的部分。
【解决方案3】:

这里可能存在几个不同的问题。

但是对于初学者来说:

1) 如果您使用的是 64 位操作系统,请确保确保您使用的是 64 位 JVM

2) 确保您的代码尽快关闭您打开的所有资源。

3) 明确设置对已完成的大对象的引用为“null”。

...和...

4) 熟悉JConsoleVisualVM

【讨论】:

  • 如果指定的堆大小太大,一般JVM会拒绝启动,例如如果没有足够的物理内存可用或使用了 32 位 JVM 并且请求了过多的内存。我假设如果 OP 已设法使用-Xmx6144m 启动 JVM,那么他们实际上使用的是 64 位操作系统和 JVM...
【解决方案4】:

您不能将 2.6 GB 的 XML 图像加载为只有 6 GB 的文档。正如 jhordo 所建议的那样,该比率更有可能是 12 比 1。这是因为每个字节都变成了 16 位字符,每个标签、属性和值都变成了至少 32 字节开销的字符串。

相反,您应该使用 SAX 或基于事件的解析器逐步处理文件。这样,它只会保留您需要保留的数据。如果您可以一次处理所有内容,则无需保留任何内容。

【讨论】:

    猜你喜欢
    • 2014-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-01
    • 2011-03-27
    • 2015-05-14
    • 2021-11-20
    相关资源
    最近更新 更多