【问题标题】:java.lang.OutOfMemoryError: Java heap space while initialising an arrayjava.lang.OutOfMemoryError:初始化数组时的 Java 堆空间
【发布时间】:2013-10-11 08:08:56
【问题描述】:

我正在尝试初始化一个大小为 10 位整数的布尔类型数组。它继续抛出 OutOfMemoryException。我已将 eclipse 的堆空间大小从 256 增加到 1024。有什么我缺少的吗?

int size = 1000000000;
boolean[] primesList = new boolean[size];

【问题讨论】:

  • 你真的需要这么大的空间吗?
  • 先计数:大小 * 4 字节加上其他对象。请改用Buffer
  • @ajozwik 你从哪里得到 size*4 字节的?
  • @GarethDavis 这可能是用于生成素数筛或任意数的素性测试,这需要像这样的随机访问数组来提高性能。

标签: java arrays initialization


【解决方案1】:

使用java.util.BitSet,与使用boolean 数组相比,它会将位打包在八分之一的空间中。

布尔数组元素占用 1 个字节而不是 1 个位的原因是因为(大多数)CPU 架构不提供直接读取和写入单个内存位的能力。 PC 可以操作的最小单位有 8 位。 JVM可以将这些位打包在一起,然后修改一个位,它会读取字节,修改它,然后写回它,但如果多个线程同时修改数组,这将不起作用。 p>

至于您的原始数组,它有 10 亿个布尔值,每个一个字节,即 10 亿字节或 ~954 MB。所以一个 1024 MB 的堆应该足够了(?)。也许它找不到足够大的连续 内存块,或者你没有正确设置内存参数。打印Runtime.getRuntime().maxMemory() 的值以找出Java 正在使用的最大堆大小。对于 1024 MB,参数应为 -Xmx1024M

最后注意事项:从 Java 7 开始,您可以在数字中使用下划线以提高可读性。所以你可以写1_000_000_000而不是1000000000

【讨论】:

    【解决方案2】:

    来自docs

    这种数据类型代表一种信息,但它的“大小”并不是精确定义的。

    如果您认为布尔值至少有一个字节,则 1000000000 字节需要 953MB 用于数组的内存。

    所以这是1024MB 中唯一占用953MB 的数组,这可能会导致问题。

    但在一个美好的世界里,我猜这个用例不需要 :)

    【讨论】:

    • 您在此处添加了一个零,并且布尔值不需要一位,至少在这种形式中。
    • 你算错了。有 10 位数字,而不是 11。
    • @ViktorOzerov 是的,你是对的,多余的零已被删除。谢谢指点。
    【解决方案3】:

    只需请求更多的堆大小,例如 -X1500M 绝对有效。您的数组占用了 1000000000 个字节,但您需要请求更多,因为 Java 堆分为新旧代。

    【讨论】:

      【解决方案4】:

      启动JVM时需要传递一个-Xmx参数来设置最大堆空间越高。

      另请注意,数组的最大大小为 Integer.MAX_VALUE

      【讨论】:

        【解决方案5】:

        您可以改用对象持有者,避免一次分配所有空间的需要——如果堆大小足够大,这可能会解决问题。您需要大量空间来在数组中保存这么多布尔值 - 确保为堆空间设置了最小和最大大小。 也可以使用 List 之类的东西来仅在需要时填写值。如果你真的需要它作为一个数组,有一些方法可以转换回来(apache commons 中的 Arrays 集合允许你使用 Arrays.toPrimitive)。

        【讨论】:

          【解决方案6】:

          布尔数组存储为字节:

          https://forums.oracle.com/thread/2550321

          我认为您需要重新考虑如何做到这一点 - 创建大小为千兆字节的数据结构超出了当前硬件的能力。

          【讨论】:

            【解决方案7】:

            由于以下两个原因,它可能非常好:

            1. 根据this 文章,JVM 不会将整个 Xmx 量分配给您的程序。幸存者空间之一占用的空间被打折,因为 JVM 在内部将其用于一些簿记或临时使用。这可能是在这种情况下 1024 MB 不够的原因,因为您的阵列已经在使用 954 MB。幸存者空间可能超过 70 MB。如下所述,增加 Xmx 可能有帮助,也可能没有帮助

            2. 根据this 文章,如果您的数据结构对于堆中的任何代(伊甸园、从/到幸存者、旧代)来说都太大,则您可能会出现 OOM。您可以使用 -XX:+PrintGCDetails 并查看每一代获得了多少。因此,您必须不断增加您的 Xmx,直到其中至少一个(eden、from/to、old gen)足够大以容纳您的对象,或者您必须明确设置不同堆区域的大小(例如,- XX:NewSize for Young gen)。

            【讨论】:

              猜你喜欢
              • 2021-09-09
              • 2011-10-24
              • 2013-11-05
              • 1970-01-01
              • 2017-05-13
              • 1970-01-01
              • 1970-01-01
              • 2011-11-05
              • 1970-01-01
              相关资源
              最近更新 更多