【问题标题】:How to avoid OutOfMemory exception in a memory intensive application in Java?如何在 Java 中的内存密集型应用程序中避免 OutOfMemory 异常?
【发布时间】:2014-01-16 19:41:31
【问题描述】:

我们开发了一个 java 应用程序,其主要目标是读取文件(输入文件),对其进行处理并将其转换为一组输出文件。

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

当输入文件为 4 GB,内存设置为 -Xms4096m -Xmx16384m 在 32 GB RAM 时,此程序运行良好

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

我们使用具有 250GB RAM 和内存设置为 -Xms40g -Xmx200g(也尝试了其他几种变体)的 linux 机器来运行应用程序并遇到 OutOfMemory 异常。

在我们项目的这个阶段,很难考虑重新设计代码以适应 hadoop(或其他大型数据处理框架),而且我们目前能够负担得起的硬件配置是 250GB 的 RAM。

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

提前致谢

【问题讨论】:

  • 这个文件被读入后,你如何在内存中存储它?
  • 如果其他答案对您不起作用,一个选择是使用内存占用较少的数据结构。我不得不推出自己的哈希表,该哈希表使用内置内存的 1/5 来管理数据,以将 JRE 堆保持在 500mb 以下。
  • 文件在被读取时被添加到其适当的自定义数据结构中并存储在内存中。我在整个转换过程中使用哈希表。
  • 存储的是什么类型的对象?如果它们是原语,则使用 Java Hashmaps 会浪费大量内存。
  • 它们不是原始数据类型,我们使用的是一些复杂的对象

标签: java hadoop memory-leaks out-of-memory


【解决方案1】:

最明显的尝试是不要将整个文件保存在内存中(如果可能的话)。所以你可以分块处理它,并且在任何时候只在内存中保留一个或几个块(而不是整个文件)。

【讨论】:

  • 我想了很多,但是数据是相互关联的,很难将文件分成块。这是我们仍在积极追求的一件事。如果在框架级别有任何支持(例如某种内存换出/换入机制),我还想探索其他选项
【解决方案2】:

尽量使用尽可能少的内存,例如,不要将整个文件保存在内存中,而是将其转储到磁盘上。

说,Hadoop HDFS 会为您做到这一点,只需通过良好的分析器或堆转储分析器检查您没有任何泄漏。

自定义解决方案可能是仍然使用普通文件,但以类似页面的方式组织访问。例如。 Java 有很好的 MappedByteBuffer,它可以让你将文件的某个部分加载到内存中以便更快地访问(在 Java 7 之前它存在某些问题,导致不可预测的取消映射,但据我所知,它已经被修复了)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多