Space 需要在内存中保留最大的整数数组

Space required to keep largest integer array in memory

我正在审查一个算法,它保留一个整数数组,输入的大小是动态的。所以根据我的计算,它可能需要

  integer MAX_VALUE  * int size  = ?   
      2^31 integers  * 4 bytes   = ?
2147483648 integers  * 4 bytes   = 8 Gigabytes

这个计算正确吗? JVM 会使用如此连续的 space 来存储 int 数组还是需要考虑其他事项?

数组大小最大值 < Integer.MAX_VALUE

不,您的最大值不正确。

Java 中数组元素数量的限制比 Integer.MAX_VALUE (2,147,483,647), depending on the version of Java, the host OS, and how Java was compiled. See by Ivan Mamontov on the Question, 少一点。

是的,最大数组 int ≈ 8 gigs

因此 int 的最大数组的大小将大致为 ( Integer.MAX_VALUE - 8L ) * 32L 位,即 68,719,476,448 位,即 8,589,934,556 个八位字节。

是的,大约 8 GB 内存。请记住:这是数组的 连续 内存。所以:

  • JVM 和宿主 OS 可能需要做大量工作才能生成这样的数组,具体取决于运行时那一刻内存的碎片化程度。
  • 如果主机硬件没有足够的实际内存,您将陷入虚拟内存,由此产生的分页可能会导致糟糕的性能。

如果您真的在工作中突破这些限制,请务必进行实际测试。您可能需要考虑为超大内存设计的 Java 替代实现,例如 Azul Systems 的 Zing

数组的理论大小为:

  • numberOfElementsInTheArray * 4 字节

  • 12 个字节的 headers(int[] 是一个 Object)。实际上 headers 的大小取决于你使用的标志和 on the JVM version you are running this

  • 4个字节来保留数组的length

  • 填充。

例如:(我准备使用JOL for this):

    int [] x = new int[10];
    for(int i=0;i<10;++i){
        x[i] = 9999;
    }
    System.out.println(GraphLayout.parseInstance((Object)x).toPrintable()); 

将输出:

 [I@7a81197dd object externals:
      ADDRESS       SIZE TYPE PATH                           VALUE
    70fe45268         56 [I                                  [9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999]

所以它有 56 bytes:

  • 40 个值本身(10 个整数 * 4 个字节)
  • 12 为 headers
  • 长度为 4
  • 0 用于填充

如果将此数组更改为 Integer,情况将发生巨大变化。 Integer 是一个 Object,因此您将在数组中存储一个引用(可以是 48 字节,具体取决于 UseCompressedOops 标志),加上每个Integer 个实例需要 2 个 headers(每个 Integer 是一个 Object)。

    Integer[] y = new Integer[10];
    for(int i=0;i<10;++i){
        y[i] = 9999;
    }

    System.out.println(GraphLayout.parseInstance((Object)y).toFootprint());

这将显示:

   [Ljava.lang.Integer;@369f73a2d footprint:
 COUNT       AVG       SUM   DESCRIPTION
     1        56        56   [Ljava.lang.Integer;
    10        16       160   java.lang.Integer
    11                 216   (total)

216 bytes:

  • 每个引用 4 个字节(我打开了 UseCompressedOop),总共 40 个字节
  • 数组的 12 个字节 headers
  • 数组长度为 4 个字节
  • 0 字节填充

该数组的每个引用都指向一个 Integer,每个 Object 都将具有 16 bytes:

  • 内部 int 的 4 个字节
  • 12 字节 headers
  • 0 字节填充