2014-01-16 15 views
0

我们开发了一个java应用程序,其主要目标是读取文件(输入文件),处理它并将其转换为一组输出文件。如何在Java中的内存密集型应用程序中避免OutOfMemory异常?

(我已经给出了我们解决方案的一般描述,以避免不相关的细节)。

这个程序工作完全正常,当输入文件为4 GB,具有-Xms4096m -Xmx16384m的内存设置在一个32 GB的RAM

现在,我们需要运行我们的大小130 GB的输入文件的应用程序。

我们使用了一个250GB内存的linux系统,内存设置为-Xms40g -Xmx200g(也尝试了其他一些变体)来运行应用程序并打出OutOfMemory异常。

在这个阶段,我们的项目是很难考虑重新设计的代码,以适应Hadoop的(或一些其它的大规模数据处理框架),也是当前的硬件配置,我们可以买得起是RAM 250GB。

您能否建议我们避免OutOfMemory异常的方法,开发这些类型的应用程序时的一般做法是什么?

在此先感谢

+0

一旦它被读入,你如何将这个文件存储在内存中? – Dodd10x

+0

如果其他答案不适用于您,其中一个选择是使用较少内存密集型数据结构。我不得不推出自己的哈希表,它使用内置的内存的1/5来管理数据,以保持JRE堆在500mb以下。 – Dodd10x

+0

正在读取的文件被添加到其正确的自定义数据结构并存储在内存中。我在整个转换过程中使用哈希表。 – user3203947

回答

1

最明显的地方就是不要在内存中保存整个文件(如果可能)。所以你可以用块来处理它,并且在任何时候在内存中保留一个或几个块(而不是整个文件)。

+0

我想了很多,但数据是相互关联的,很难将文件分成块。这是我们仍在积极追求的一件事。如果在框架级别有任何支持(例如某种内存交换/交换机制),我还想研究其他选项, – user3203947

1

只要尽量保持使用尽可能少的内存,比如说,不要将整个文件保存在内存中,将其转储到磁盘上。假设,Hadoop HDFS可以为你做到这一点,只需通过一个好的分析器或堆转储分析器检查你是否有任何泄漏。

自定义解决方案可能仍然使用纯文件,但以类似页面的方式组织访问。例如。 Java有很好的MappedByteBuffer,它可以让你将一段文件加载到内存中以加快访问速度(在Java 7之前它有一些问题,导致不可预知的解映射,但就我所知它已经被修复)。

相关问题