Skip to content
Permalink
Browse files
8230744: Several classes throw OutOfMemoryError without message
Reviewed-by: psandoz, martin, bchristi, rriggs, smarks
  • Loading branch information
JimLaskey committed Jun 11, 2020
1 parent 2085fd3 commit 03642a01af7123298d6524a98c99a3934d35c11b
Showing 9 changed files with 27 additions and 53 deletions.
@@ -31,6 +31,7 @@
import java.util.Spliterator;
import java.util.stream.IntStream;
import java.util.stream.StreamSupport;
import jdk.internal.util.ArraysSupport;

import static java.lang.String.COMPACT_STRINGS;
import static java.lang.String.UTF16;
@@ -239,7 +240,7 @@ private void ensureCapacityInternal(int minimumCapacity) {

/**
* Returns a capacity at least as large as the given minimum capacity.
* Returns the current capacity increased by the same amount + 2 if
* Returns the current capacity increased by the current length + 2 if
* that suffices.
* Will not return a capacity greater than
* {@code (MAX_ARRAY_SIZE >> coder)} unless the given minimum capacity
@@ -250,26 +251,14 @@ private void ensureCapacityInternal(int minimumCapacity) {
* greater than (Integer.MAX_VALUE >> coder)
*/
private int newCapacity(int minCapacity) {
// overflow-conscious code
int oldCapacity = value.length >> coder;
int newCapacity = (oldCapacity << 1) + 2;
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
return (newCapacity <= 0 || SAFE_BOUND - newCapacity < 0)
? hugeCapacity(minCapacity)
: newCapacity;
}

private int hugeCapacity(int minCapacity) {
int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
int UNSAFE_BOUND = Integer.MAX_VALUE >> coder;
if (UNSAFE_BOUND - minCapacity < 0) { // overflow
throw new OutOfMemoryError();
int oldLength = value.length;
int newLength = minCapacity << coder;
int growth = newLength - oldLength;
int length = ArraysSupport.newLength(oldLength, growth, oldLength + (2 << coder));
if (length == Integer.MAX_VALUE) {
throw new OutOfMemoryError("Required length exceeds implementation limit");
}
return (minCapacity > SAFE_BOUND)
? minCapacity : SAFE_BOUND;
return length >> coder;
}

/**
@@ -2187,7 +2187,7 @@ public String replace(CharSequence target, CharSequence replacement) {
resultLen = Math.addExact(thisLen, Math.multiplyExact(
Math.addExact(thisLen, 1), replLen));
} catch (ArithmeticException ignored) {
throw new OutOfMemoryError();
throw new OutOfMemoryError("Required length exceeds implementation limit");
}

StringBuilder sb = new StringBuilder(resultLen);
@@ -3571,15 +3571,14 @@ public String repeat(int count) {
if (len == 0 || count == 0) {
return "";
}
if (Integer.MAX_VALUE / count < len) {
throw new OutOfMemoryError("Required length exceeds implementation limit");
}
if (len == 1) {
final byte[] single = new byte[count];
Arrays.fill(single, value[0]);
return new String(single, coder);
}
if (Integer.MAX_VALUE / count < len) {
throw new OutOfMemoryError("Repeating " + len + " bytes String " + count +
" times will produce a String exceeding maximum size.");
}
final int limit = len * count;
final byte[] multiple = new byte[limit];
System.arraycopy(value, 0, multiple, 0, len);
@@ -357,7 +357,7 @@ public static String replace(byte[] value, int valLen, byte[] targ,
resultLen = Math.addExact(valLen,
Math.multiplyExact(++p, replLen - targLen));
} catch (ArithmeticException ignored) {
throw new OutOfMemoryError();
throw new OutOfMemoryError("Required length exceeds implementation limit");
}
if (resultLen == 0) {
return "";
@@ -661,7 +661,7 @@ public static String replace(byte[] value, int valLen, boolean valLat1,
resultLen = Math.addExact(valLen,
Math.multiplyExact(++p, replLen - targLen));
} catch (ArithmeticException ignored) {
throw new OutOfMemoryError();
throw new OutOfMemoryError("Required length exceeds implementation limit");
}
if (resultLen == 0) {
return "";
@@ -53,6 +53,7 @@
import java.util.function.Consumer;
import java.util.function.Predicate;
import jdk.internal.access.SharedSecrets;
import jdk.internal.util.ArraysSupport;

/**
* An unbounded {@linkplain BlockingQueue blocking queue} that uses
@@ -136,14 +137,6 @@
*/
private static final int DEFAULT_INITIAL_CAPACITY = 11;

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

/**
* Priority queue represented as a balanced binary heap: the two
* children of queue[n] are queue[2*n+1] and queue[2*(n+1)]. The
@@ -298,16 +291,9 @@ private void tryGrow(Object[] array, int oldCap) {
if (allocationSpinLock == 0 &&
ALLOCATIONSPINLOCK.compareAndSet(this, 0, 1)) {
try {
int newCap = oldCap + ((oldCap < 64) ?
(oldCap + 2) : // grow faster if small
(oldCap >> 1));
if (newCap - MAX_ARRAY_SIZE > 0) { // possible overflow
int minCap = oldCap + 1;
if (minCap < 0 || minCap > MAX_ARRAY_SIZE)
throw new OutOfMemoryError();
newCap = MAX_ARRAY_SIZE;
}
if (newCap > oldCap && queue == array)
int growth = oldCap < 64 ? oldCap + 2 : oldCap >> 1;
int newCap = ArraysSupport.newLength(oldCap, 1, growth);
if (queue == array)
newArray = new Object[newCap];
} finally {
allocationSpinLock = 0;
@@ -1681,7 +1681,7 @@ else if (temp[i + 1] != 'Q')
try {
newTempLen = Math.addExact(j + 2, Math.multiplyExact(3, pLen - i));
} catch (ArithmeticException ae) {
throw new OutOfMemoryError();
throw new OutOfMemoryError("Required pattern length too large");
}
int[] newtemp = new int[newTempLen];
System.arraycopy(temp, 0, newtemp, 0, j);
@@ -629,7 +629,7 @@ public long allocateMemory(long bytes) {

long p = allocateMemory0(bytes);
if (p == 0) {
throw new OutOfMemoryError();
throw new OutOfMemoryError("Unable to allocate " + bytes + " bytes");
}

return p;
@@ -685,7 +685,7 @@ public long reallocateMemory(long address, long bytes) {

long p = (address == 0) ? allocateMemory0(bytes) : reallocateMemory0(address, bytes);
if (p == 0) {
throw new OutOfMemoryError();
throw new OutOfMemoryError("Unable to allocate " + bytes + " bytes");
}

return p;
@@ -46,7 +46,7 @@ public UnsyncByteArrayOutputStream() {

public void write(byte[] arg0) {
if ((VM_ARRAY_INDEX_MAX_VALUE - pos) < arg0.length) {
throw new OutOfMemoryError();
throw new OutOfMemoryError("Required length exceeds implementation limit");
}
int newPos = pos + arg0.length;
if (newPos > size) {
@@ -58,7 +58,7 @@ public void write(byte[] arg0) {

public void write(byte[] arg0, int arg1, int arg2) {
if ((VM_ARRAY_INDEX_MAX_VALUE - pos) < arg2) {
throw new OutOfMemoryError();
throw new OutOfMemoryError("Required length exceeds implementation limit");
}
int newPos = pos + arg2;
if (newPos > size) {
@@ -70,7 +70,7 @@ public void write(byte[] arg0, int arg1, int arg2) {

public void write(int arg0) {
if (VM_ARRAY_INDEX_MAX_VALUE - pos == 0) {
throw new OutOfMemoryError();
throw new OutOfMemoryError("Required length exceeds implementation limit");
}
int newPos = pos + 1;
if (newPos > size) {
@@ -116,4 +116,4 @@ private void expandSize(int newPos) {
buf = newBuf;
size = newSize;
}
}
}
@@ -244,7 +244,7 @@ private void grow(int minCapacity) {

private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
throw new OutOfMemoryError("Required length exceeds implementation limit");
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;

0 comments on commit 03642a0

Please sign in to comment.