2

I want to get the exact amount of memory which is needed to create the biggest possible array in Java.

My Test Program:

public class MemoryOfArraysTest {
    public static void main(String... args) {
        Object[] array = new Object[Integer.MAX_VALUE - 2];
    }
}

I know from own testing that the maximum length of an array is Integer.MAX_VALUE - 2 (2147483645).

If the number is greater you will get following error:

Exception in thread "main" java.lang.OutOfMemoryError: Requested array size exceeds VM limit
at MemoryOfArraysTest.main(MemoryOfArraysTest.java:3)

But this is only one step getting closer to the maximum length of an array. The other problem is the memory your VM can use. You can specify the memory with -Xmx.

If I run my class with with java -Xmx1g MemoryOfArraysTest (only 1GB of memory) I get expected error:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at MemoryOfArraysTest.main(MemoryOfArraysTest.java:3)

If I run it with java -Xmx10g MemoryOfArraysTest (10GB of memory) it just works.

This is what I have so far. But what is the exact amount of memory my program needs? Preferably in KB´s. Is there maybe a way to calculate it?

Lasnik
  • 256
  • 2
  • 11
  • 2
    This is a really cool concept, but like, why? – Gunnarhawk Mar 19 '21 at 18:38
  • 2
    Integer.MAX_VALUE - 2 == 2147483646 elements in the array. On a 64-bit VM with `-XX:+UseCompressedOops` (the default) a reference takes 4 bytes. The array header currently on OpenJDK takes 16 bytes (https://stackoverflow.com/questions/17335884/object-header-size-in-java-on-64bit-vm-with-4gb-ram, note that Zing and OpenJ9 can be different, and project [Lilliput](https://mail.openjdk.java.net/pipermail/discuss/2021-March/005720.html) is eventually coming), so 2147483646 * 4 + 16 bytes. But why? This is rarely needed to know. What problem are you solving, what are you trying to achieve? – Petr Janeček Mar 19 '21 at 18:39
  • It is effectively impossible to find out. Or at least, it's infeasible. You cannot know how much heap space is taken by other classes that are loaded by the classloader (e.g. all the java.lang crap). Without knowing that, you can't know how much of the heap is left for you. The exact amount of heap used by the stuff that's loaded by default will vary slightly between pretty much every single build of the JDK. – Michael Mar 19 '21 at 18:54
  • 1
    Sidenote: the biggest possible array would be a `long[]` or `double[]` since each entry would take up `64` bits, or `8` Bytes. Doing the calculation with the biggest possible array size (`Integer.MAX_VALUE = 2^31 - 1`) yields a size slightly over `16` GB (`17179869192` bytes) – Turing85 Mar 19 '21 at 19:00
  • 2
    Of cource it doesn´t have a real usecase. I am not trying to create an array with such a length. I was just really curios what an equation would be and how arrays are managed in general in Java. But I thought asking it like that wouldn´t get answered. Because my question wouldn´t be really clear. Thanks to all the comments with answers. They help me to understand the topic of memory a bit more. – Lasnik Mar 19 '21 at 19:04

1 Answers1

1

Each Object has two headers, with XX:+UseCompressedOops (which is on by default), the two headers will have 12 bytes. Plus 4 bytes to keep the length of the array. Plus some eventual padding that you need to take into account also.

You can use JOL to find out how big it is. An experiment like this:

    Object[] array = new Object[100];
    for(int i=0;i<100;++i){
        array[i] = new Object();
    }

    System.out.println(GraphLayout.parseInstance(array).totalSize());

shows that it has 1600 bytes. If I change that size to 1000, I will get 16000 bytes.

But that math, you can say that the size of Object[2147483646] is going to be around 34 GB.


Notice that there is a big difference between populating that array and not. If it is not populated:

Object[] array = new Object[Integer.MAX_VALUE - 2];
System.out.println(ClassLayout.parseInstance(array).instanceSize()); 

It will weight arund 8GB

Eugene
  • 117,005
  • 15
  • 201
  • 306
  • I have `32 GB` of RAM on my mac, and even if I try to increase swap, my mac will shutdown when trying to calculate a populated array of that size – Eugene Mar 19 '21 at 19:21