【问题标题】:Java Out of Memory Array ErrorJava 内存不足数组错误
【发布时间】:2014-06-30 22:20:42
【问题描述】:

我正在尝试将大量 long 存储到一个数组中,但我的数组和 ArrayList 出现 OOM 错误。

    ArrayList<Long> A = new ArrayList<Long>();
    Long[] B = new Long[100000000];

    for(int i = 0; i < 100000000; i++) A.add(i);        
    for(int i = 0; i < 100000000; i++) B[i] = (long) i;

//Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
//at java.lang.Integer.valueOf(Unknown Source)

还有其他简单的数据结构可以用来存储如此大量的长整数或整数吗?

【问题讨论】:

  • 您是否有理由不只是为 JVM 提供更大的堆?
  • 无论你使用什么数据结构,大量的long/int` 值都会占用一定的内存——对于 1 亿个值,对于 ints 和 400 MB longs 为 800 MB。数组尽可能精简
  • 堆大小的设置是什么? 1 亿 Long 并不是特别大。要设置堆大小限制,请使用“-Xmx”java 命令行选项。参考:docs.oracle.com/javase/7/docs/technotes/tools/windows/java.html
  • 你想用这些做什么?您是否真的需要存储一个连续的整数列表,或者这是否适用于您实际上具有较少可预测值的应用程序,例如随机生成的值?

标签: java arrays out-of-memory


【解决方案1】:

如果在运行java 时正确使用-Xmx 标志(有关详细信息,请参阅here),您可以增加堆大小。如果需要,这将允许您以受控方式使用更多内存。据我所知,没有办法从程序本身“请求”更多堆内存(类似于在 C 中运行 sbrk() 或 mmap() 系统调用)

正如我链接到的答案所说:

例如,像这样启动 JVM 将使用 256MB 内存,并允许进程使用多达 2048MB 的内存:

java -Xmx2048m -Xms256m

此外,您可以使用“k”、“m”或“g”分别表示千字节、兆字节和千兆字节。 但是,您不能超过 1GB(即堆大小),除非您使用的是 64 位 JVM。

如果您 do the math 使用您的特定用例,假设 64 位 long * 100000000 需要大约 800MB 的空间。

【讨论】:

  • 你是对的,但值得一提的是,-Xmx2g 仅适用于 64 位 JVM。
【解决方案2】:

您的程序是否要求您存储多头数据?如果您要使用整数而不是长整数,那么您可以存储更多,无论哪种方式,什么需要您在数组中存储这么多长整数?

其他解决方案:

当您使用参数 -Xmx2G 启动程序时,您可以为程序提供更多堆空间 或大于标准 512M 或 1G 的其他长度

您可以处理较少数量的数组值,然后将数组保存到硬盘。然后处理数组的其余部分并将其存储到文件中。(需要 Java 垃圾收集的基本知识)

【讨论】:

    【解决方案3】:

    任何解决方案都取决于您要执行的操作。例如,如果你只是想遍历值,你可以声明一个Iterator&lt;Long&gt;

    Iterator<Long> myIterator = new Iterator<Long>() {
      private long nextValue = 0;
    
      @Override
      public boolean hasNext() {
        return nextValue < 100000000;
      }
    
      @Override
      public Long next() {
        return nextValue++;
      }
    
      @Override
      public void remove() { throw new UnsupportedOperationException(); }
    };
    

    这样的解决方案具有O(1) 内存使用率,因为它不需要您存储超过下一个值的任何内容。但它可能不适合应用程序。

    【讨论】:

    • 当数组本身导致OutOfMemoryError 时,这将无济于事。此外,我看不出创建一个额外的对象如何通过一个简单的循环来帮助解决内存问题。这也不能回答问题——Iterator 不是数据结构。
    • 你是否需要明确存储所有的 long ?您是否要在处理一次值后重用它?如果没有 OP 试图做的事情的背景,我会说这可能是一个合理的解决方案。
    • 数组一次分配所有空间,因此如果您遇到数组的 OOM 错误,这些问题无关紧要。对于错误的问题,“这可能是一个合理的解决方案”。 OP 询问的是存储值,而不是迭代它们。
    • 如果你不需要显式存储它们,你不需要首先分配数组。
    • 我想 OP 会足够聪明,不会存储不需要存储的东西。如果您不确定 OP 想要什么,请发表评论而不是回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-20
    相关资源
    最近更新 更多