java—保留内存中最大整数数组所需的空间

5tmbdcev  于 2021-06-29  发布在  Java
关注(0)|答案(2)|浏览(307)

我正在回顾一个算法,它保持一个整数数组,输入的大小是动态的。所以根据我的计算

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

这个计算正确吗?jvm会使用如此多的连续空间来存储int数组,还是需要考虑其他事情?

vpfxa7rd

vpfxa7rd1#

数组大小最大值<integer.max\u值

不,你的最大值不正确。
在java中,数组中元素的数量限制比 Integer.MAX_VALUE (2147483647),这取决于java的版本、主机操作系统以及java的编译方式。请看ivan mamontov对这个问题的回答,为什么我不能创建一个大尺寸的数组?。

是的,int的最大数组≈ 8场演出

所以最大数组的大小 int 大概是 ( Integer.MAX_VALUE - 8L ) * 32L 位是68719476448位是8589934556八位字节。
所以是的,大约8吉格的内存。记住:这是数组的连续内存。所以:
jvm和主机操作系统可能需要做大量的工作来生成这样一个数组,这取决于运行时内存的碎片化程度。
如果主机硬件没有足够的实际内存,您将进入虚拟内存,由此产生的分页可能会导致糟糕的性能。
如果你真的在工作中突破了这些限制,就要经常进行真实世界的测试。您可能需要考虑为超大内存设计的java的替代实现,例如azul系统的zing。

w1jd8yoj

w1jd8yoj2#

阵列的理论尺寸为:
numberofelementsinthearray*4字节
12字节头( int[] 是一个对象)。实际上,头的大小取决于您使用的标志和您运行的jvm版本
4字节以保持 length 数组的
衬垫。
例如:(我要用jol来表示这个):

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用于收割台
长度为4
0用于填充
如果将此数组更改为 Integer ,事情发生了巨大的变化。 Integer 是一个对象,因此您将在数组中存储一个引用(可以是 4 或者 8 字节,取决于 UseCompressedOops 标志),加上 Integer 示例将需要2个标头(每个 Integer 是一个对象)。

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字节头
数组的4字节长度
0字节填充
该数组中的每个引用都指向一个 Integer ,每个对象都将具有 16 bytes :
内部4字节 int 他们坚持住了
12字节头
0字节填充

相关问题