Mismatch between JDK and JVM re largest byte array that VM can allocate?
Srinivas Ramakrishna
ysr1729 at gmail.com
Mon Mar 11 23:11:10 UTC 2013
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.MAX_VALUE;
112 }
113 buf = Arrays.copyOf(buf, newCapacity);
114 }
This can result in a request for an array of size Integer.MAX_VALUE
(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
<tt>(byte)0</tt>.
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
<tt>newLength</tt> is negative
2888 * @throws NullPointerException if <tt>original</tt> 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.MAX_VALUE 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::object_size(scale, length, header_size) without causing an
// overflow. We also need to make sure that this will not overflow a size_t on
// 32 bit platforms when we convert it to a byte size.
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;
}
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 max_jint 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
More information about the core-libs-dev
mailing list