< prev index next >
src/java.base/share/classes/java/lang/AbstractStringBuilder.java
Print this page
rev 13764 : [mq]: 8149330-Friendly-realloc-in-StringBuilder
@@ -136,38 +136,57 @@
* This method has the same contract as ensureCapacity, but is
* never synchronized.
*/
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
- int capacity = value.length >> coder;
- if (minimumCapacity - capacity > 0) {
- expandCapacity(minimumCapacity);
+ int oldCapacity = value.length >> coder;
+ if (minimumCapacity - oldCapacity > 0) {
+ value = Arrays.copyOf(value,
+ newCapacity(minimumCapacity) << coder);
}
}
/**
- * This implements the expansion semantics of ensureCapacity with no
- * size check or synchronization.
+ * The maximum size of array to allocate (unless necessary).
+ * 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 void expandCapacity(int minimumCapacity) {
- int newCapacity = (value.length >> coder) * 2 + 2;
- if (newCapacity - minimumCapacity < 0) {
- newCapacity = minimumCapacity;
- }
- if (newCapacity < 0) {
- if (minimumCapacity < 0) {// overflow
- throw new OutOfMemoryError();
- }
- newCapacity = Integer.MAX_VALUE;
+ private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
+
+ /**
+ * Returns a capacity at least as large as the given minimum capacity.
+ * Returns the current capacity increased by the same amount + 2 if
+ * that suffices.
+ * Will not return a capacity greater than (MAX_ARRAY_SIZE >> coder)
+ * unless the given minimum capacity is greater than that.
+ *
+ * @param minCapacity the desired minimum capacity
+ * @throws OutOfMemoryError if minCapacity is less than zero or
+ * 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;
}
- if (coder != LATIN1 && newCapacity > StringUTF16.MAX_LENGTH) {
- if (minimumCapacity >= StringUTF16.MAX_LENGTH) {
+
+ 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();
}
- newCapacity = StringUTF16.MAX_LENGTH;
- }
- this.value = Arrays.copyOf(value, newCapacity << coder);
+ return (minCapacity > SAFE_BOUND)
+ ? minCapacity : SAFE_BOUND;
}
/**
* If the coder is "isLatin1", this inflates the internal 8-bit storage
* to 16-bit <hi=0, low> pair storage.
< prev index next >