diff --git a/common/src/java/org/apache/hadoop/hive/common/io/NonSyncByteArrayOutputStream.java b/common/src/java/org/apache/hadoop/hive/common/io/NonSyncByteArrayOutputStream.java index ea49231..0a38041 100644 --- a/common/src/java/org/apache/hadoop/hive/common/io/NonSyncByteArrayOutputStream.java +++ b/common/src/java/org/apache/hadoop/hive/common/io/NonSyncByteArrayOutputStream.java @@ -21,12 +21,22 @@ import java.io.DataInput; import java.io.IOException; import java.io.OutputStream; +import java.util.Arrays; /** * A thread-not-safe version of ByteArrayOutputStream, which removes all * synchronized modifiers. */ public class NonSyncByteArrayOutputStream extends ByteArrayOutputStream { + + /** + * 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; + public NonSyncByteArrayOutputStream(int size) { super(size); } @@ -71,18 +81,22 @@ public void write(int b) { count += 1; } - private int enLargeBuffer(int increment) { - int temp = count + increment; - int newLen = temp; - if (temp > buf.length) { - if ((buf.length << 1) > temp) { - newLen = buf.length << 1; - } - byte newbuf[] = new byte[newLen]; - System.arraycopy(buf, 0, newbuf, 0, count); - buf = newbuf; + private void enLargeBuffer(int increment) { + if (increment <= 0) { + return; + } + + // Increase size by a factor of 1.5x + final int oldCapacity = buf.length; + int newCapacity = oldCapacity + (oldCapacity >> 1); + + // Check for overflow scenarios + if (newCapacity < 0 || newCapacity > MAX_ARRAY_SIZE) { + newCapacity = MAX_ARRAY_SIZE; + } else if (newCapacity < increment) { + newCapacity = increment; } - return newLen; + buf = Arrays.copyOf(buf, newCapacity); } /**