2015-10-29 37 views
1

我正在从具有大量数据的IO中读取数据,并且需要将数据存储在Map或属性文件中的键值对中,然后我才可以使用该数据生成报告。但是,当我将这些庞大的数据存储在Map或Properties文件中时,堆内存异常即将到来。相反,如果我使用SQLLite,则需要花费非常多的时间来检索它。有没有什么不同的方式来实现这一点。请建议。如何避免Java中的Java堆空间异常

+0

[Java堆内存错误(可能的重复http://stackoverflow.com/questions/3443937/java-heap-memory-error) – Reinard

+0

对于这种情况,如果我们增加堆,问题仍然存在,请不要增加堆以任何方式给我建议 –

+0

你可以做的是读取数据块的字节,将其存储在地图上,然后进一步处理。从您的问题中我可以看到,您正在读取大量数据并将其存储在地图或属性文件中,因为您正在处理大量数据并充分利用JVM。可能这可能是你获得堆空间异常的原因。试一试大块头 –

回答

0

增加堆大小是一个选项,但使用内存映射文件java.You可以参考this

+0

在我们的例子中,我们正在读取来自配置单元的数据,并试图将数据放入地图或根据一些匹配的条件。读取文件后,我们可以使用RandomAccessFile来提供先生。 –

2

Java堆空间要点

  1. 的Java存储堆外的数据替代堆内存是由操作系统分配给JVM的内存的一部分。

  2. 每当我们创建对象时,它们都是在Java中的堆内部创建的。

  3. Java堆空间被分为三个区域或一代,为了垃圾收集而被称为新一代,旧的或老生代或彼尔姆空间。永久生成是在热点JVM中在完整gc期间收集的垃圾。

  4. 通过使用JVM命令行选项-Xms,-Xmx和-Xmn,可以增加或更改Java堆空间的大小。在指定大小以指示Mega或Gig之后,不要忘记添加单词“M”或“G”。 例如,您可以通过执行以下命令java -Xmx256m javaClassName(您的程序类名称)将java堆大小设置为258MB。

  5. 您可以使用JConsole或Runtime.maxMemory(),Runtime.totalMemory(),Runtime.freeMemory()查询Java中编程的堆大小。

  6. 您可以使用命令“jmap”在Java中进行堆转储,并使用“jhat”来分析堆转储。

  7. Java堆空间不同于用于存储调用层次结构和局部变量的堆栈。

  8. Java垃圾回收器负责从死对象中回收内存并返回到Java堆空间。

  9. 当你得到java.lang.OutOfMemoryError时,不要惊慌,有时它只是增加堆大小的问题,但如果它是经常性的,那么在Java中寻找内存泄漏。

  10. 使用事件探查器和堆转储分析器工具来了解Java堆空间以及为每个对象分配了多少内存。

参考链接查看更多细节:

https://docs.oracle.com/cd/E19159-01/819-3681/abeii/index.html

https://docs.oracle.com/cd/E40520_01/integrator.311/integratoretl_users/src/ti_troubleshoot_memory_errors.html

2

你需要做的的需要为您的地图存储一个粗略的估计。多少个键和值?键和值有多大?例如,如果键长,并且值的字符串平均长度为40个字符,则20亿个键值对的绝对最小值为(40 + 8)* 2E9 - 大约100 GB。当然,真正的要求大于最小估计值 - 根据键和值的性质,要大两倍。

如果估计的内存超出合理范围(100 GB超出了合理范围,除非您有很多钱),则需要找出一种划分处理的方法。你需要读入大量的数据,然后在其上运行一些算法以将其缩小到一定的尺寸。然后逐个处理所有其他块,确保在处理新块时不要将旧块留在周围。最后,查看所有块的结果并计算最终结果。为了更好地描述这种方法,请查看“map-reduce”。

如果估计的内存量有些合理(比如说8 GB - 而且有16 GB的机器) - 使用64位JVM,设置最大堆内存使用-Xmx开关,确保使用最有效的数据结构,如特罗韦地图。

祝你好运!

相关问题