changeset 59740:49a68abdb0ba

8230744: Several classes throw OutOfMemoryError without message Reviewed-by: psandoz, martin, bchristi, rriggs, smarks
author jlaskey
date Thu, 11 Jun 2020 10:08:23 -0300
parents 19b3969274ce
children 870cdacc1766
files src/java.base/share/classes/java/lang/AbstractStringBuilder.java src/java.base/share/classes/java/lang/String.java src/java.base/share/classes/java/lang/StringLatin1.java src/java.base/share/classes/java/lang/StringUTF16.java src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java src/java.base/share/classes/java/util/regex/Pattern.java src/java.base/share/classes/jdk/internal/misc/Unsafe.java src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/UnsyncByteArrayOutputStream.java src/jdk.zipfs/share/classes/jdk/nio/zipfs/ByteArrayChannel.java
diffstat 9 files changed, 27 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java	Thu Jun 11 12:51:09 2020 +0200
+++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java	Thu Jun 11 10:08:23 2020 -0300
@@ -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 @@
 
     /**
      * 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 @@
      *         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 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");
         }
-        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();
-        }
-        return (minCapacity > SAFE_BOUND)
-            ? minCapacity : SAFE_BOUND;
+        return length >> coder;
     }
 
     /**
--- a/src/java.base/share/classes/java/lang/String.java	Thu Jun 11 12:51:09 2020 +0200
+++ b/src/java.base/share/classes/java/lang/String.java	Thu Jun 11 10:08:23 2020 -0300
@@ -2187,7 +2187,7 @@
                 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 @@
         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);
--- a/src/java.base/share/classes/java/lang/StringLatin1.java	Thu Jun 11 12:51:09 2020 +0200
+++ b/src/java.base/share/classes/java/lang/StringLatin1.java	Thu Jun 11 10:08:23 2020 -0300
@@ -357,7 +357,7 @@
             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 "";
--- a/src/java.base/share/classes/java/lang/StringUTF16.java	Thu Jun 11 12:51:09 2020 +0200
+++ b/src/java.base/share/classes/java/lang/StringUTF16.java	Thu Jun 11 10:08:23 2020 -0300
@@ -661,7 +661,7 @@
             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 "";
--- a/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java	Thu Jun 11 12:51:09 2020 +0200
+++ b/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java	Thu Jun 11 10:08:23 2020 -0300
@@ -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
@@ -137,14 +138,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
      * priority queue is ordered by comparator, or by the elements'
@@ -298,16 +291,9 @@
         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;
--- a/src/java.base/share/classes/java/util/regex/Pattern.java	Thu Jun 11 12:51:09 2020 +0200
+++ b/src/java.base/share/classes/java/util/regex/Pattern.java	Thu Jun 11 10:08:23 2020 -0300
@@ -1681,7 +1681,7 @@
         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);
--- a/src/java.base/share/classes/jdk/internal/misc/Unsafe.java	Thu Jun 11 12:51:09 2020 +0200
+++ b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java	Thu Jun 11 10:08:23 2020 -0300
@@ -629,7 +629,7 @@
 
         long p = allocateMemory0(bytes);
         if (p == 0) {
-            throw new OutOfMemoryError();
+            throw new OutOfMemoryError("Unable to allocate " + bytes + " bytes");
         }
 
         return p;
@@ -685,7 +685,7 @@
 
         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;
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/UnsyncByteArrayOutputStream.java	Thu Jun 11 12:51:09 2020 +0200
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/UnsyncByteArrayOutputStream.java	Thu Jun 11 10:08:23 2020 -0300
@@ -46,7 +46,7 @@
 
     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, 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(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 @@
         buf = newBuf;
         size = newSize;
     }
-}
\ No newline at end of file
+}
--- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ByteArrayChannel.java	Thu Jun 11 12:51:09 2020 +0200
+++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ByteArrayChannel.java	Thu Jun 11 10:08:23 2020 -0300
@@ -244,7 +244,7 @@
 
     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;