Mismatch between JDK and JVM re largest byte array that VM can allocate? (original) (raw)
David Holmes david.holmes at oracle.com
Tue Mar 12 01:25:28 UTC 2013
- Previous message: Mismatch between JDK and JVM re largest byte array that VM can allocate?
- Next message: Mismatch between JDK and JVM re largest byte array that VM can allocate?
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Hi Ramki,
The maximum array size is a VM limitation based on the internal implementation, so I don't think the JDK code should be aware of this limitation.
At least with the present code the request for a size of Integer.MAX_VALUE will fail immediately, rather than spending half an hour failing to allocate an insanely large array ;-)
If huge arrays eventually make their way into Java we will have to address this, but otherwise it seems pretty low priority to me.
Is this actually causing an issue or is it just an observation?
Cheers, David
On 12/03/2013 9:11 AM, Srinivas Ramakrishna wrote:
I am looking at code in (for example) ByteArrayOutputStream.java :-
96 /** 97 * Increases the capacity to ensure that it can hold at least the 98 * number of elements specified by the minimum capacity argument. 99 * 100 * @param minCapacity the desired minimum capacity 101 */ 102 private void grow(int minCapacity) { 103 // overflow-conscious code 104 int oldCapacity = buf.length; 105 int newCapacity = oldCapacity << 1; 106 if (newCapacity - minCapacity < 0) 107 newCapacity = minCapacity; 108 if (newCapacity < 0) { 109 if (minCapacity < 0) // overflow 110 throw new OutOfMemoryError(); 111 newCapacity = Integer.MAXVALUE; 112 } 113 buf = Arrays.copyOf(buf, newCapacity); 114 }
This can result in a request for an array of size Integer.MAXVALUE (because of line 111 above), see below:- 2874 /** 2875 * Copies the specified array, truncating or padding with zeros (if necessary) 2876 * so the copy has the specified length. For all indices that are 2877 * valid in both the original array and the copy, the two arrays will 2878 * contain identical values. For any indices that are valid in the 2879 * copy but not the original, the copy will contain (byte)0. 2880 * Such indices will exist if and only if the specified length 2881 * is greater than that of the original array. 2882 * 2883 * @param original the array to be copied 2884 * @param newLength the length of the copy to be returned 2885 * @return a copy of the original array, truncated or padded with zeros 2886 * to obtain the specified length 2887 * @throws NegativeArraySizeException if newLength is negative 2888 * @throws NullPointerException if original is null 2889 * @since 1.6 2890 */ 2891 public static byte[] copyOf(byte[] original, int newLength) { 2892 byte[] copy = new byte[newLength]; 2893 System.arraycopy(original, 0, copy, 0, 2894 Math.min(original.length, newLength)); 2895 return copy; 2896 } So the call at line 2892 can cause a request for an array with Integer.MAXVALUE entries, yet the JVM doesn't give you arrays that large; witness this code in arrayOop.cpp where this will flatten out:- // Return the maximum length of an array of BasicType. The length can passed // to typeArrayOop::objectsize(scale, length, headersize) without causing an // overflow. We also need to make sure that this will not overflow a sizet on // 32 bit platforms when we convert it to a byte size. static int32t maxarraylength(BasicType type) { assert(type >= 0 && type < TCONFLICT, "wrong type"); assert(type2aelembytes(type) != 0, "wrong type"); const sizet maxelementwordspersizet = alignsizedown((SIZEMAX/HeapWordSize - headersize(type)), MinObjAlignment); const sizet maxelementspersizet = HeapWordSize * maxelementwordspersizet / type2aelembytes(type); if ((sizet)maxjint < maxelementspersizet) { // It should be ok to return maxjint here, but parts of the code // (CollectedHeap, Klass::oopoopiterate(), 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 alignsizedown(maxjint - headersize(type), MinObjAlignment); } return (int32t)maxelementspersizet; } Is there any plan to fix this mismatch ? May be it's as simple(!) as checking the GC code to make sure it doesn't traffic in int's and fix the code above to return maxjint for the byte array case as well? I have a vague recollection of a bug id already for this, but it's been a while.... Thanks! -- ramki
- Previous message: Mismatch between JDK and JVM re largest byte array that VM can allocate?
- Next message: Mismatch between JDK and JVM re largest byte array that VM can allocate?
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]