Why is it not possible in Java to create an array of size MAX_INT?

I read several answers to this question ( Why can't I create a large array? And https://bugs.openjdk.java.net/browse/JDK-8029587 ) and I don't understand the following. "In the GC code, we pass the size of objects in words as int". As I know, the word size in JVM is 4 bytes. Accordingly, if we pass the size of a long, large array (e.g. MAX_INT-5) in words as int, we should get an OutOfMemoryException with the requested array size exceeding the VM limit, because the size is too large for an int even without the header size. So why do arrays of different types have the same limit for the maximum number of elements?

+3


source to share


2 answers


Only addressing why arrays of different types have the same limit for the maximum number of elements? part:

Because it doesn't really matter in practical reality; but makes it easier to implement code that implements the JVM.



If there is only one ; it's the same for all array types; then you can process all arrays with this code. Instead of having a lot of type code.

And given the fact that people who need "large" arrays can create them; and only those that need very large arrays affect ; why waste this effort?

+2


source


The answer is in the jdk sources as far as I can tell (I'm looking at jdk-9); also after writing it, I'm not sure if it should be a comment instead (and if it answers your question), but it's too long for a comment ...

First the error is deduced from hotspot/src/share/vm/oops/arrayKlass.cpp

here:

if (length > arrayOopDesc::max_array_length(T_ARRAY)) {
   report_java_out_of_memory("Requested array size exceeds VM limit");
    ....
}

      

Now it T_ARRAY

is actually a type enumeration BasicType

that looks like this:

public static final BasicType T_ARRAY = new BasicType(tArray);
// tArray is an int with value = 13

      



This is the first sign that when calculating the maximum size, jdk does not care what will hold this array ( T_ARRAY

does not indicate what types will hold this array).

Now the method that actually checks the size of the maximum array looks like this:

 static int32_t max_array_length(BasicType type) {
      assert(type >= 0 && type < T_CONFLICT, "wrong type");
      assert(type2aelembytes(type) != 0, "wrong type");

      const size_t max_element_words_per_size_t =
      align_size_down((SIZE_MAX/HeapWordSize - header_size(type)), MinObjAlignment);
      const size_t max_elements_per_size_t =
      HeapWordSize * max_element_words_per_size_t / type2aelembytes(type);
      if ((size_t)max_jint < max_elements_per_size_t) {
         // It should be ok to return max_jint here, but parts of the code
         // (CollectedHeap, Klass::oop_oop_iterate(), and more) uses an int for
         // passing around the size (in words) of an object. So, we need to avoid
         // overflowing an int when we add the header. See CRs 4718400 and 7110613.
         return align_size_down(max_jint - header_size(type), MinObjAlignment);
      }
       return (int32_t)max_elements_per_size_t;
}

      

I didn't dive into the code too much, but it's based on HeapWordSize

; which is equal to 8 bytes at least

. here is a good link (I tried to find it in the code itself, but there are too many links to it).

+1


source







All Articles