Java 为什么我不能创建一个大尺寸的数组?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31382531/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 11:00:38  来源:igfitidea点击:

Why I can't create an array with large size?

javajvmjvm-hotspot

提问by JohnWinter

Why it is impossible to create an array with max int size?

为什么不可能创建一个最大 int 大小的数组?

int i = 2147483647;
int[] array = new int[i];

I found this explanation:

我找到了这个解释:

Java arrays are accessed via 32-bit ints, resulting in a maximum theoretical array size of 2147483647 elements.

Java 数组通过 32 位整数访问,导致最大理论数组大小为 2147483647 个元素。

But as you can see my code doesn't work. It is also impossible to create an array with size

但是正如您所看到的,我的代码不起作用。创建一个大小的数组也是不可能的

new int[Integer.MAX_VALUE - 5];

Technical details

技术细节

  • 64-Bit HotSpot JVM
  • OSX 10.10.4
  • 64 位热点 JVM
  • OSX 10.10.4

PS

聚苯乙烯

And why -5actually?

为什么-5呢?

采纳答案by Ivan Mamontov

Theory

理论

There are two possible exceptions:

有两种可能的例外:

  • OutOfMemoryError: Java heap spacemeans your array does not fit into java heap space. In order to solve you can increase the maximum heap size by using JVM option -Xmx. Also take into account that the maximum size of object cannot be larger than the largest heap generation.
  • OutOfMemoryError: Requested array size exceeds VM limitmeans platform-specific size was exceeded:
    • the upper bound limit is set by the restrictions of the size type used to describe an index in the array, so theoretical array size is limited by 2^31-1=2147483647elements.
    • the other limit is JVM/platform specific. According to chapter 10: Arrays of The Java Language Specification, Java SE 7 Editionthere is no strict limit on array length, thus array size may be reduced without violating JLS.
  • OutOfMemoryError: Java heap space意味着您的数组不适合 java 堆空间。为了解决这个问题,您可以使用 JVM 选项增加最大堆大小-Xmx。还要考虑到对象的最大大小不能大于最大的堆代
  • OutOfMemoryError: Requested array size exceeds VM limit表示超出了平台特定的大小:
    • 上限是由用于描述数组中索引的大小类型的限制设置的,因此理论上的数组大小受2^31-1=2147483647元素的限制。
    • 另一个限制是特定于 JVM/平台的。根据第 10 章:Java 语言规范的数组,Java SE 7 版对数组长度没有严格限制,因此可以在不违反 JLS 的情况下减小数组大小。

Practice

实践

In HotSpot JVM array size is limited by internal representation. In the GC code JVM passes around the size of an array in heap words as an intthen converts back from heap words to jintthis may cause an overflow. So in order to avoid crashes and unexpected behavior the maximum array length is limited by (max size - header size). Where header sizedepends on C/C++ compiler which was used to build the JVM you are running(gcc for linux, clang for macos), and runtime settings(like UseCompressedClassPointers). For example on my linux:

在 HotSpot JVM 中,数组大小受内部表示的限制。在 GC 代码中,JVM 在堆字中传递数组的大小,int然后从堆字转换回jint这可能会导致溢出。因此,为了避免崩溃和意外行为,最大数组长度受(max size - header size) 限制。凡头的大小依赖于C / C ++编译器,用于构建正在运行的JVM(GCC为Linux,铛适用于MacOS)和运行时设置(如UseCompressedClassPointers)。例如在我的 linux 上:

  • Java HotSpot(TM) 64-Bit Server VM 1.6.0_45 limit Integer.MAX_VALUE
  • Java HotSpot(TM) 64-Bit Server VM 1.7.0_72 limit Integer.MAX_VALUE-1
  • Java HotSpot(TM) 64-Bit Server VM 1.8.0_40 limit Integer.MAX_VALUE-2
  • Java HotSpot(TM) 64 位服务器 VM 1.6.0_45 限制 Integer.MAX_VALUE
  • Java HotSpot(TM) 64 位服务器 VM 1.7.0_72 限制 Integer.MAX_VALUE-1
  • Java HotSpot(TM) 64 位服务器 VM 1.8.0_40 限制 Integer.MAX_VALUE-2

Useful Links

有用的链接

回答by Ankur Anand

Some VMs reserve some header words in an array.

一些 VM 在数组中保留一些头字。

The maximum "safe" number would be 2 147 483 639 (Integer.MAX_VALUE - 8)

最大的“安全”数字将 be 2 147 483 639 (Integer.MAX_VALUE - 8)

Source-http://www.docjar.com/html/api/java/util/ArrayList.java.html

源码-http://www.docjar.com/html/api/java/util/ArrayList.java.html

**
  191        * The maximum size of array to allocate.
  192        * Some VMs reserve some header words in an array.
  193        * Attempts to allocate larger arrays may result in
  194        * OutOfMemoryError: Requested array size exceeds VM limit
  195        */
  196       private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

So It depends on the maximum memory available to your JVM on your SYSTEM NOW

所以这取决于现在系统上 JVM 可用的最大内存

Edit : Why It's Showing OOM.

编辑:为什么它显示 OOM。

Number of Elements = 2 147 483 639

元素数 = 2 147 483 639

number of bytes required for one element = 4

一个元素所需的字节数 = 4

Total Memory for just Element 8589934556 KB == 8.589934555999999 GB

仅 Element 的总内存 8589934556 KB == 8.589934555999999 GB

Now If the total memory usage of the array is not a multiple of 8 bytes, then the size is rounded up to the next mutlitple of 8 .

现在,如果数组的总内存使用量不是 8 字节的倍数,则大小将四舍五入到下一个 8 的倍数。

So You need more than what you are allocating due to Overheads too and that should be continuous memory

因此,您需要的不仅仅是由于开销而分配的内容,而且应该是连续内存

回答by Marko Topolnik

It's not enough to just have enough heap for that allocation; you need to have a single heap regionof sufficient size. As you know, heap is divided into generations.

仅仅为该分配拥有足够的堆是不够的;您需要有一个足够大的堆区域。如您所知,堆分为几代。

For a single allocation of 8 GB you must ensure that much for a single heap region (plus some overhead). With 12 GB of -Xmxyou may still be short. Use additional options to control the size of the Old Generation.

对于 8 GB 的单个分配,您必须确保单个堆区域的分配(加上一些开销)。使用 12 GB,-Xmx您可能仍然不够用。使用附加选项来控制老年代的大小。

回答by sactiw

Well, Ivan has already correctly pointed out that the array length does have a well defined upper limit and that it is again JVM/Platform dependent. In fact, more importantly, he also stated that how much length of array you can actually create in your code will mainly be controlled by how much max heap space you have allocated to your program while execution.

好吧,Ivan 已经正确地指出数组长度确实有一个明确定义的上限,并且它再次依赖于 JVM/平台。事实上,更重要的是,他还表示,您可以在代码中实际创建多少数组长度主要取决于您在执行时为程序分配了多少最大堆空间。

I would just like to add small code snippet to support his explanation. For example, theoretically, an array [] should accept length <= INTEGER.MAX_VALUE - x (here x is header size that is again JVM/Platform specific) but suppose you run followingJava program with VM option -Xmx32mthen you will see that none of the created array reach the length close to MAX_ARRAY_SIZE (i.e. 2147483639)

我只想添加小代码片段来支持他的解释。例如,从理论上讲,数组 [] 应该接受长度 <= INTEGER.MAX_VALUE - x(这里 x 是头大小,也是 JVM/平台特定的)但假设您使用 VM 选项-Xmx32m运行以下Java 程序,那么您将看到创建的数组都没有达到接近 MAX_ARRAY_SIZE 的长度(即 2147483639)

byte[] array : 1 byte
0 l=1048576 s=1mb
1 l=2097152 s=2mb
2 l=4194304 s=4mb
3 l=8388608 s=8mb
java.lang.OutOfMemoryError: Java heap space l=16777216 s=16mb

byte[] 数组:1 字节
0 l=1048576 s=1mb
1 l=2097152 s=2mb
2 l=4194304 s=4mb
3 l=8388608 s=8mb
java.lang.OutOfMemoryError:Java 堆空间 l=1677721mb6

char[] array : 2 byte
0 l=1048576 s=2mb
1 l=2097152 s=4mb
2 l=4194304 s=8mb
java.lang.OutOfMemoryError: Java heap space l=8388608 s=16mb

char[] 数组:2 字节
0 l=1048576 s=2mb
1 l=2097152 s=4mb
2 l=4194304 s=8mb
java.lang.OutOfMemoryError:Java 堆空间 l=8388608 s=16mb

int[] array : 4 byte
0 l=1048576 s=4mb
1 l=2097152 s=8mb
java.lang.OutOfMemoryError: Java heap space l=4194304 s=16mb

int[] 数组:4 字节
0 l=1048576 s=4mb
1 l=2097152 s=8mb
java.lang.OutOfMemoryError:Java 堆空间 l=4194304 s=16mb

double[] array : 8 byte
0 l=1048576 s=8mb
java.lang.OutOfMemoryError: Java heap space l=2097152 s=16mb

double[] 数组:8 字节
0 l=1048576 s=8mb
java.lang.OutOfMemoryError:Java 堆空间 l=2097152 s=16mb

Below is the code:

下面是代码:

    byte[] barray = null;
    System.out.println("\nbyte[] array : 1 byte");
    try {
        for (ii=0; ii < 32; ii++) {
            barray = new byte[(int)Math.pow(2, ii)*1024*1024];
            System.out.println(ii + " l=" + barray.length + " s=" + barray.length / (1024 * 1024) + "mb");
        }
    }
    catch (Throwable e) {
        barray = null;
        System.out.println(e + " l=" + (int)Math.pow(2, ii)*1024*1024 + " s=" + (int)Math.pow(2, ii)*1024*1024 / (1024 * 1024) + "mb");
    }

    char[] carray = null;
    System.out.println("\nchar[] array : 2 byte");
    try {
        for (ii=0; ii < 32; ii++) {
            carray = new char[(int)Math.pow(2, ii)*1024*1024];
            System.out.println(ii + " l=" + carray.length + " s=" + 2*carray.length / (1024 * 1024) + "mb");
        }
    }
    catch (Throwable e) {
        carray = null;
        System.out.println(e + " l=" + (int)Math.pow(2, ii)*1024*1024 + " s=" + 2*(int)Math.pow(2, ii)*1024*1024 / (1024 * 1024) + "mb");
    }

    int[] iarray = null;
    System.out.println("\nint[] array : 4 byte");
    try {
        for (ii=0; ii < 32; ii++) {
            iarray = new int[(int)Math.pow(2, ii)*1024*1024];
            System.out.println(ii + " l=" + iarray.length + " s=" + 4*iarray.length / (1024 * 1024) + "mb");
        }
    }
    catch (Throwable e) {
        iarray = null;
        System.out.println(e + " l=" + (int)Math.pow(2, ii)*1024*1024 + " s=" + 4*(int)Math.pow(2, ii)*1024*1024 / (1024 * 1024) + "mb");
    }

    double[] darray = null;
    System.out.println("\ndouble[] array : 8 byte");
    try {
        for (ii=0; ii < 32; ii++) {
            darray = new double[(int)Math.pow(2, ii)*1024*1024];
            System.out.println(ii + " l=" + darray.length + " s=" + 8*darray.length / (1024 * 1024) + "mb");
        }
    }
    catch (Throwable e) {
        darray = null;
        System.out.println(e + " l=" + (int)Math.pow(2, ii)*1024*1024 + " s=" + 8*(int)Math.pow(2, ii)*1024*1024 / (1024 * 1024) + "mb");
    }

回答by Anonymous

find your max heap size by going to cmd and enter this line

通过转到 cmd 并输入此行来找到您的最大堆大小

javaw -XX:+PrintFlagsFinal | find "MaxHeapSize"

and then divide it by 1.5, you will get the approximate maximum size of the array for your computer

然后将其除以1.5,您将获得计算机数组的近似最大大小