diff --git a/src/share/classes/sun/misc/IOUtils.java b/src/share/classes/sun/misc/IOUtils.java index e857b6a7955fa490da1f85c8a3f224cff853a76b..5cba87982e058bd2a9b50d99a8b11004fb19d6b6 100644 --- a/src/share/classes/sun/misc/IOUtils.java +++ b/src/share/classes/sun/misc/IOUtils.java @@ -33,7 +33,9 @@ import java.io.EOFException; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.Objects; public class IOUtils { @@ -140,30 +142,55 @@ public class IOUtils { * @since 1.9 */ public static byte[] readAllBytes(InputStream is) throws IOException { - byte[] buf = new byte[DEFAULT_BUFFER_SIZE]; - int capacity = buf.length; - int nread = 0; + List bufs = null; + byte[] result = null; + int total = 0; int n; - for (;;) { - // read to EOF which may read more or less than initial buffer size - while ((n = is.read(buf, nread, capacity - nread)) > 0) - nread += n; + do { + byte[] buf = new byte[DEFAULT_BUFFER_SIZE]; + int nread = 0; - // if the last call to read returned -1, then we're done - if (n < 0) - break; + // read to EOF which may read more or less than buffer size + while ((n = is.read(buf, nread, buf.length - nread)) > 0) { + nread += n; + } - // need to allocate a larger buffer - if (capacity <= MAX_BUFFER_SIZE - capacity) { - capacity = capacity << 1; - } else { - if (capacity == MAX_BUFFER_SIZE) + if (nread > 0) { + if (MAX_BUFFER_SIZE - total < nread) { throw new OutOfMemoryError("Required array size too large"); - capacity = MAX_BUFFER_SIZE; + } + total += nread; + if (result == null) { + result = buf; + } else { + if (bufs == null) { + bufs = new ArrayList<>(); + bufs.add(result); + } + bufs.add(buf); + } + } + } while (n >= 0); // if the last call to read returned -1, then break + + if (bufs == null) { + if (result == null) { + return new byte[0]; } - buf = Arrays.copyOf(buf, capacity); + return result.length == total ? + result : Arrays.copyOf(result, total); } - return (capacity == nread) ? buf : Arrays.copyOf(buf, nread); + + result = new byte[total]; + int offset = 0; + int remaining = total; + for (byte[] b : bufs) { + int len = Math.min(b.length, remaining); + System.arraycopy(b, 0, result, offset, len); + offset += len; + remaining -= len; + } + + return result; } /** diff --git a/test/sun/misc/IOUtils/ReadAllBytes.java b/test/sun/misc/IOUtils/ReadAllBytes.java index 2d7a30b2b2ed6cf0790a4551c7d1df8da7d5412f..440aad09a34ee8193f198c48934ac395d5aaabc5 100644 --- a/test/sun/misc/IOUtils/ReadAllBytes.java +++ b/test/sun/misc/IOUtils/ReadAllBytes.java @@ -34,7 +34,7 @@ import sun.misc.IOUtils; /* * @test - * @bug 8080835 + * @bug 8080835 8193832 * @library /lib/testlibrary * @build jdk.testlibrary.* * @run main ReadAllBytes @@ -50,15 +50,11 @@ public class ReadAllBytes { test(new byte[]{}); test(new byte[]{1, 2, 3}); test(createRandomBytes(1024)); - test(createRandomBytes((1 << 13) - 1)); - test(createRandomBytes((1 << 13))); - test(createRandomBytes((1 << 13) + 1)); - test(createRandomBytes((1 << 15) - 1)); - test(createRandomBytes((1 << 15))); - test(createRandomBytes((1 << 15) + 1)); - test(createRandomBytes((1 << 17) - 1)); - test(createRandomBytes((1 << 17))); - test(createRandomBytes((1 << 17) + 1)); + for (int shift : new int[] {13, 14, 15, 17}) { + for (int offset : new int[] {-1, 0, 1}) { + test(createRandomBytes((1 << shift) + offset)); + } + } } static void test(byte[] expectedBytes) throws IOException {