< prev index next >

src/java.base/share/classes/java/lang/AbstractStringBuilder.java

Print this page
rev 13764 : [mq]: 8149330-Friendly-realloc-in-StringBuilder

@@ -143,29 +143,35 @@
             expandCapacity(minimumCapacity);
         }
     }
 
     /**
+     * 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 static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
+
+    /**
      * This implements the expansion semantics of ensureCapacity with no
      * size check or synchronization.
      */
     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;
-        }
-        if (coder != LATIN1 && newCapacity > StringUTF16.MAX_LENGTH) {
-            if (minimumCapacity >= StringUTF16.MAX_LENGTH) {
+
+        final int SAFE_BOUND = (MAX_ARRAY_SIZE >> coder);
+        if (((SAFE_BOUND - newCapacity) | newCapacity) < 0) {
+            final int UNSAFE_BOUND = (Integer.MAX_VALUE >> coder);
+            if (UNSAFE_BOUND - minimumCapacity < 0) { // overflow
                 throw new OutOfMemoryError();
             }
-            newCapacity = StringUTF16.MAX_LENGTH;
+            newCapacity = (minimumCapacity > SAFE_BOUND)
+                    ? minimumCapacity : SAFE_BOUND;
         }
         this.value = Arrays.copyOf(value, newCapacity << coder);
     }
 
     /**
< prev index next >