我从具有大量数据的IO读取数据,我需要将数据存储在Map或属性文件中的键值对中,然后我才能使用该数据生成报告。但是,当我将这些巨大的数据存储在Map或Properties文件中时,Heap Memory Exception即将到来。相反,如果我使用SQLLite,则需要花费大量时间来检索它。有没有不同的方法来实现这一点。请建议。
答案 0 :(得分:2)
Java堆空间重点
Java堆内存是操作系统分配给JVM的内存的一部分。
每当我们创建对象时,都会在Java中的Heap中创建它们。
Java堆空间分为三个区域或生成,以便进行垃圾收集,称为新一代,旧生成或终身生成或Perm空间。永久生成是在热点JVM中的完整gc期间进行垃圾收集。
您可以使用JVM命令行选项-Xms,-Xmx和-Xmn来增加或更改Java堆空间的大小。在指定大小以指示Mega或Gig之后,不要忘记添加单词“M”或“G”。 例如,您可以通过执行以下命令java -Xmx256m javaClassName(您的程序类名称)将Java堆大小设置为258MB。
您可以使用JConsole或Runtime.maxMemory(),Runtime.totalMemory(),Runtime.freeMemory()来查询Java中的程序块大小。
您可以使用命令“jmap”在Java中使用堆转储,并使用“jhat”来分析该堆转储。
Java堆空间与堆栈不同,堆栈用于存储调用层次结构和局部变量。
Java垃圾收集器负责从死对象中回收内存并返回Java堆空间。
当你得到java.lang.OutOfMemoryError时不要惊慌,有时它只是增加堆大小的问题,但如果它是经常性的,那么在Java中寻找内存泄漏。
使用Profiler和Heap dump Analyzer工具了解Java堆空间以及为每个对象分配的内存量。
参考链接了解更多详情:
https://docs.oracle.com/cd/E19159-01/819-3681/abeii/index.html
答案 1 :(得分:2)
您需要粗略估计地图所需的内存。有多少键和值?键和值有多大?例如,如果键是长的并且值是平均40个字符长的字符串,则20亿个键值对的绝对最小值是(40 + 8)* 2E9 - 大约100 GB。当然,实际要求大于最小估计值 - 根据键和值的性质,大到两倍。
如果估计的内存量超出合理范围(100 GB超出合理范围,除非你有很多钱),你需要找到一种方法来划分你的处理。您需要读入大量数据,然后在其上运行一些算法以将其减小到一些小尺寸。然后逐个为所有其他块执行此操作,确保在处理新块时不保留旧块。最后,查看所有块的结果并计算最终结果。有关此方法的更好描述,请查找“map-reduce”。
如果估计的内存量有些合理(例如,8 GB - 并且你有16 GB的机器) - 使用64位JVM,使用-Xmx开关设置最大堆内存,请确保使用最有效的数据像Trove地图这样的结构。
祝你好运!答案 2 :(得分:0)
增加堆大小是一种选择,但是有一种替代方法可以通过在java中使用内存映射文件来存储数据。您可以参考this