1

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

但是我仍然收到堆空间内存不足错误?

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

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

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

4

4 回答 4

8

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

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

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

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

底线:

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

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

于 2012-12-28T16:55:45.200 回答
1

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

于 2012-12-28T16:57:41.460 回答
1

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

但对于初学者:

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

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

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

... 和 ...

4) 熟悉JConsoleVisualVM

于 2012-12-28T16:58:03.917 回答
1

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

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

于 2012-12-28T17:04:29.537 回答