0

When i initialize the StringBuffer constructor with Integer.MAX_VALUE it throws OutOfMemoryError and when i add 16 to it it throws NegativeArraySizeException

  public class Test {
        public static void main(String[] arg) {
            StringBuffer sb = new StringBuffer(Integer.MAX_VALUE + 16);
            sb.append("A");
        }
    }

Can some one help me understand this behavior?

6
  • Int overflow... Commented May 5, 2017 at 5:33
  • Read up about integer overflow Commented May 5, 2017 at 5:33
  • 1
    1st: Integer.MAX_VALUE + 16 is an overflow that produce a negative number → invalid argument Commented May 5, 2017 at 5:34
  • An int plus an int is always an int, even if the addition overflows the limits of an int. Commented May 5, 2017 at 5:37
  • I reopened this question because integer overflow may not be the only thing happening here. Commented May 5, 2017 at 5:37

3 Answers 3

1

You have actually asked two entirely different questions here, so they must be addressed separately.

1. Why does new StringBuffer(Integer.MAX_VALUE) throw an OutOfMemoryError?

The StringBuffer constructor tries to instantiate an array of char, whose size is the value that you pass. So you're implicitly trying to instantiate an array of size Integer.MAX_VALUE. There are two reasons why you might get an OutOfMemoryError from instantiating an array.

The first reason is that you genuinely don't have enough heap space. Without knowing what else is going on in your program, or what your heap settings are, it's impossible for me to tell whether that might be happening for you. But you can choose the maximum heap size for your JVM when you start it up, with the -Xmx option. Obviously, you'd need to set it to several gigabytes to get this to work (for example -Xmx8g), assuming your computer has enough RAM.

The second reason for an OutOfMemoryError when instantiating an array is that you've exceeded the maximum array size. That's definitely happening here. The maximum array size is not defined by the Java Language Specification, and it varies from JVM to JVM. In most modern JVMs, the maximum array size is Integer.MAX_VALUE - 2, but there are JVMs in which the maximum is Integer.MAX_VALUE - 5 or Integer.MAX_VALUE - 8. In any case, Integer.MAX_VALUE is over the limit for sure.

2. Why does new StringBuffer(Integer.MAX_VALUE + 16) throw a NegativeArraySizeException?

This is to do with integer arithmetic in Java. Any int value has to be between Integer.MIN_VALUE and Integer.MAX_VALUE. Also, when you add two int values, the answer is guaranteed by the Java Language Specification to be an int. Therefore, when you evaluateInteger.MAX_VALUE + 16`, you're not going to get the mathematically correct answer. In fact, what Java does is to work mod 232. Another way of looking at it is that the JVM will add or subtract multiples of 232 to bring the answer within the correct range.

That means that the value of Integer.MAX_VALUE + 16 will actually be numerically equal to Integer.MAX_VALUE + 16 -232, which is a large negative number. As I mentioned earlier, the StringBuffer constructor tries to instantiate an array whose size is the value that you pass. This attempt to instantiate an array of negative size gives you your NegativeArraySizeException.

Sign up to request clarification or add additional context in comments.

Comments

0

A StringBuffer uses a character array in its implementation to store a string. Here is the constructor of its super class, AbstractStringBuilder, where the array actually gets allocated:

AbstractStringBuilder(int capacity) {
    value = new char[capacity];
}

As you can see, a new char[] array gets initialized with the capacity integer you passed in. The max size for character arrays in Java is the smaller of the heap size or Integer.MAX_VALUE. If the following code threw an error, then my guess is that your heap ran out of memory:

StringBuffer sb = new StringBuffer(Integer.MAX_VALUE);

I would have expected this to work, assuming the heap had enough space. But trying to allocate a StringBuffer of size Integer.MAX_VALUE + 16 can't work, because it would exceed the max size of the underlying char[] array.

2 Comments

I maybe left out information about integer overflow, which also could be happening even before the array allocation takes place. But this is one possible explanation for what is happening.
OOM is justifiable but question here is Negative Integer exception ??
0

If you add 1 to Integer.MAX_VALUE you will end up with Integer.MIN_VALUE. From here on you should know what happens when you add 16:

Integer.MAX_VALUE + 16 == Integer.MAX_VALUE + 1 + 15 == Integer.MIN_VALUE + 15

Explanation

Integers in Java are represented by 32-Bits while the most significant one (the left most bit) denotes the sign of the Integer (0 == positive, 1 == negative).

Integer.MAX_VALUE is represented as: 01111111111111111111111111111111. Adding 1 will flip all 1s to 0s and flip the left most 0 to 1 resulting in 10000000000000000000000000000000 which is a negative number, more specific Integer.MIN_VALUE.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.