mirror of https://github.com/apache/lucene.git
LUCENE-5844: ArrayUtil.grow/oversize now returns at most Integer.MAX_VALUE - 8
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1612935 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
d9660bcd42
commit
b293b947cb
|
@ -205,6 +205,10 @@ Bug Fixes
|
||||||
|
|
||||||
* LUCENE-5838: Fix hunspell when the .aff file has over 64k affixes. (Robert Muir)
|
* LUCENE-5838: Fix hunspell when the .aff file has over 64k affixes. (Robert Muir)
|
||||||
|
|
||||||
|
* LUCENE-5844: ArrayUtil.grow/oversize now returns a maximum of
|
||||||
|
Integer.MAX_VALUE - 8 for the maximum array size. (Robert Muir,
|
||||||
|
Mike McCandless)
|
||||||
|
|
||||||
Test Framework
|
Test Framework
|
||||||
|
|
||||||
* LUCENE-5786: Unflushed/ truncated events file (hung testing subprocess).
|
* LUCENE-5786: Unflushed/ truncated events file (hung testing subprocess).
|
||||||
|
|
|
@ -28,13 +28,10 @@ import java.util.Comparator;
|
||||||
|
|
||||||
public final class ArrayUtil {
|
public final class ArrayUtil {
|
||||||
|
|
||||||
/** Maximum length for an array; we set this to "a
|
/** Maximum length for an array (Integer.MAX_VALUE - 8). stackoverflow
|
||||||
* bit" below Integer.MAX_VALUE because the exact max
|
* consensus seems to be this value and it's also what ArrayList.java
|
||||||
* allowed byte[] is JVM dependent, so we want to avoid
|
* uses as its limit. */
|
||||||
* a case where a large value worked during indexing on
|
public static final int MAX_ARRAY_LENGTH = Integer.MAX_VALUE - 8;
|
||||||
* one JVM but failed later at search time with a
|
|
||||||
* different JVM. */
|
|
||||||
public static final int MAX_ARRAY_LENGTH = Integer.MAX_VALUE - 256;
|
|
||||||
|
|
||||||
private ArrayUtil() {} // no instance
|
private ArrayUtil() {} // no instance
|
||||||
|
|
||||||
|
@ -169,6 +166,10 @@ public final class ArrayUtil {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (minTargetSize > MAX_ARRAY_LENGTH) {
|
||||||
|
throw new IllegalArgumentException("requested array size " + minTargetSize + " exceeds maximum array in java (" + MAX_ARRAY_LENGTH + ")");
|
||||||
|
}
|
||||||
|
|
||||||
// asymptotic exponential growth by 1/8th, favors
|
// asymptotic exponential growth by 1/8th, favors
|
||||||
// spending a bit more CPU to not tie up too much wasted
|
// spending a bit more CPU to not tie up too much wasted
|
||||||
// RAM:
|
// RAM:
|
||||||
|
@ -184,9 +185,9 @@ public final class ArrayUtil {
|
||||||
int newSize = minTargetSize + extra;
|
int newSize = minTargetSize + extra;
|
||||||
|
|
||||||
// add 7 to allow for worst case byte alignment addition below:
|
// add 7 to allow for worst case byte alignment addition below:
|
||||||
if (newSize+7 < 0) {
|
if (newSize+7 < 0 || newSize+7 > MAX_ARRAY_LENGTH) {
|
||||||
// int overflowed -- return max allowed array size
|
// int overflowed, or we exceeded the maximum array length
|
||||||
return Integer.MAX_VALUE;
|
return MAX_ARRAY_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Constants.JRE_IS_64BIT) {
|
if (Constants.JRE_IS_64BIT) {
|
||||||
|
|
|
@ -43,21 +43,13 @@ public abstract class PriorityQueue<T> {
|
||||||
// We allocate 1 extra to avoid if statement in top()
|
// We allocate 1 extra to avoid if statement in top()
|
||||||
heapSize = 2;
|
heapSize = 2;
|
||||||
} else {
|
} else {
|
||||||
if (maxSize > ArrayUtil.MAX_ARRAY_LENGTH) {
|
// NOTE: we add +1 because all access to heap is
|
||||||
// Don't wrap heapSize to -1, in this case, which
|
// 1-based not 0-based. heap[0] is unused.
|
||||||
// causes a confusing NegativeArraySizeException.
|
heapSize = maxSize + 1;
|
||||||
// Note that very likely this will simply then hit
|
|
||||||
// an OOME, but at least that's more indicative to
|
if (heapSize > ArrayUtil.MAX_ARRAY_LENGTH) {
|
||||||
// caller that this values is too big. We don't +1
|
|
||||||
// in this case, but it's very unlikely in practice
|
|
||||||
// one will actually insert this many objects into
|
|
||||||
// the PQ:
|
|
||||||
// Throw exception to prevent confusing OOME:
|
// Throw exception to prevent confusing OOME:
|
||||||
throw new IllegalArgumentException("maxSize must be <= " + ArrayUtil.MAX_ARRAY_LENGTH + "; got: " + maxSize);
|
throw new IllegalArgumentException("maxSize must be <= " + (ArrayUtil.MAX_ARRAY_LENGTH-1) + "; got: " + maxSize);
|
||||||
} else {
|
|
||||||
// NOTE: we add +1 because all access to heap is
|
|
||||||
// 1-based not 0-based. heap[0] is unused.
|
|
||||||
heapSize = maxSize + 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// T is unbounded type, so this unchecked cast works always:
|
// T is unbounded type, so this unchecked cast works always:
|
||||||
|
|
|
@ -29,7 +29,7 @@ public class TestArrayUtil extends LuceneTestCase {
|
||||||
long copyCost = 0;
|
long copyCost = 0;
|
||||||
|
|
||||||
// Make sure ArrayUtil hits Integer.MAX_VALUE, if we insist:
|
// Make sure ArrayUtil hits Integer.MAX_VALUE, if we insist:
|
||||||
while(currentSize != Integer.MAX_VALUE) {
|
while (currentSize != ArrayUtil.MAX_ARRAY_LENGTH) {
|
||||||
int nextSize = ArrayUtil.oversize(1+currentSize, RamUsageEstimator.NUM_BYTES_OBJECT_REF);
|
int nextSize = ArrayUtil.oversize(1+currentSize, RamUsageEstimator.NUM_BYTES_OBJECT_REF);
|
||||||
assertTrue(nextSize > currentSize);
|
assertTrue(nextSize > currentSize);
|
||||||
if (currentSize > 0) {
|
if (currentSize > 0) {
|
||||||
|
@ -44,11 +44,24 @@ public class TestArrayUtil extends LuceneTestCase {
|
||||||
public void testMaxSize() {
|
public void testMaxSize() {
|
||||||
// intentionally pass invalid elemSizes:
|
// intentionally pass invalid elemSizes:
|
||||||
for(int elemSize=0;elemSize<10;elemSize++) {
|
for(int elemSize=0;elemSize<10;elemSize++) {
|
||||||
assertEquals(Integer.MAX_VALUE, ArrayUtil.oversize(Integer.MAX_VALUE, elemSize));
|
assertEquals(ArrayUtil.MAX_ARRAY_LENGTH, ArrayUtil.oversize(ArrayUtil.MAX_ARRAY_LENGTH, elemSize));
|
||||||
assertEquals(Integer.MAX_VALUE, ArrayUtil.oversize(Integer.MAX_VALUE-1, elemSize));
|
assertEquals(ArrayUtil.MAX_ARRAY_LENGTH, ArrayUtil.oversize(ArrayUtil.MAX_ARRAY_LENGTH-1, elemSize));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testTooBig() {
|
||||||
|
try {
|
||||||
|
ArrayUtil.oversize(ArrayUtil.MAX_ARRAY_LENGTH+1, 1);
|
||||||
|
fail("did not hit exception");
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testExactLimit() {
|
||||||
|
assertEquals(ArrayUtil.MAX_ARRAY_LENGTH, ArrayUtil.oversize(ArrayUtil.MAX_ARRAY_LENGTH, 1));
|
||||||
|
}
|
||||||
|
|
||||||
public void testInvalidElementSizes() {
|
public void testInvalidElementSizes() {
|
||||||
final Random rnd = random();
|
final Random rnd = random();
|
||||||
final int num = atLeast(10000);
|
final int num = atLeast(10000);
|
||||||
|
|
Loading…
Reference in New Issue