You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hive.apache.org by go...@apache.org on 2019/03/11 05:53:07 UTC

[hive] 02/02: HIVE-21371: Make NonSyncByteArrayOutputStream Overflow Conscious (David Mollitor, reviewed by Gopal V)

This is an automated email from the ASF dual-hosted git repository.

gopalv pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git

commit c3939dab9c7d9429464add3e95741de76e78a3ab
Author: David Mollitor <da...@gmail.com>
AuthorDate: Sun Mar 10 22:50:44 2019 -0700

    HIVE-21371: Make NonSyncByteArrayOutputStream Overflow Conscious (David Mollitor, reviewed by Gopal V)
    
    Signed-off-by: Gopal V <go...@apache.org>
---
 .../common/io/NonSyncByteArrayOutputStream.java    | 37 +++++++++++++++-------
 1 file changed, 26 insertions(+), 11 deletions(-)

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..7e09cc8 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.ByteArrayOutputStream;
 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 class NonSyncByteArrayOutputStream extends ByteArrayOutputStream {
     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;
+  private void enLargeBuffer(final int increment) {
+    final int requestCapacity = Math.addExact(count, increment);
+    final int currentCapacity = buf.length;
+
+    if (requestCapacity > currentCapacity) {
+      // Increase size by a factor of 1.5x
+      int newCapacity = currentCapacity + (currentCapacity >> 1);
+
+      // Check for overflow scenarios
+      if (newCapacity < 0 || newCapacity > MAX_ARRAY_SIZE) {
+        newCapacity = MAX_ARRAY_SIZE;
+      } else if (newCapacity < requestCapacity) {
+        newCapacity = requestCapacity;
       }
-      byte newbuf[] = new byte[newLen];
-      System.arraycopy(buf, 0, newbuf, 0, count);
-      buf = newbuf;
+      buf = Arrays.copyOf(buf, newCapacity);
     }
-    return newLen;
   }
 
   /**
@@ -93,7 +107,8 @@ public class NonSyncByteArrayOutputStream extends ByteArrayOutputStream {
     if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length)
         || ((off + len) < 0)) {
       throw new IndexOutOfBoundsException();
-    } else if (len == 0) {
+    }
+    if (len == 0) {
       return;
     }
     enLargeBuffer(len);