Thursday, September 9, 2010

java.lang.OutOfMemoryError with StringBuilder or StringBuffer

StringBuilder or StringBuffer are used for string manipulations. Yet they fail some times.
Both the final classes are the extension for packaged scoped abstract class named "java.lang.AbstractStringBuilder". These builder/buffer classes holds character array and append or manipulate this char[] each time we perform operations on it. The default char[] size is 16 although this can be specified while creating the object. When append() method is called upon StringBuilder/StringBuffer, the capacity of this char[] is checked if the String/char/any other object can be added to ongoing char[] buffer. If the character buffer size is less. I.e. not sufficient enough to append more, the capacity is doubled . Lets say its capacity was 16, and not sufficient to add more, than the the capacity is increased by doubling the size of current buffer length. This keeps happening when you keep on appending stuffs to it. Common case is while reading a file and storing it inside memory in form of a StringBuilder. You never know what the size of file could be. when size isn't sufficient for the StringBuilder, buffer size is doubled and this keeps growing. A point will reach when System is not able to
allocate enough space for the buffer. Bang! following exception or rather Error is encountered.
Exception in thread
"main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2882)
at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:100)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:390)
at java.lang.StringBuilder.append(StringBuilder.java:119)

Root cause

The problem with StringBuilder I see is it doubles the capacity from current length. Lets say the internal char buffer length is 65000 and more 100 chars has to be added than the buffer capacity is doubled to 65000 * 2. If we dive into the code of Arrays.copyOf() method line no# 2882. It tries to create a new char[] of size 65000 * 2 (in our case).
char[] copy = new char[newLength];
And this will throw Error if the Java Virtual machine does not have enough to allocate.

Solution/Fix

How do we get rid of such OutOfMemoryError? Decide what are we going to hold in StringBuilder's class buffer. It is always better to use StringBuilder/StringBuffer instead of performing string operations like
String myString = "some string" + "another string" + "and another string";
But if we have to read some file and then write that into some file back again then, go for Streams. This is what the purpose of Streams or Writer/Reader are. Decide the buffer length and use streams to work in such cases. If that is not workable in the situation, than the common approach for solving java.lang.OutOfMemoryError is to increase the JVM memory via parameters like -Xmx256m
java.exe -Xmx256m

Conclusion:

Strings manipulation is always a performance over head. implement the best practices and best applicable solution as when to use normal String concatenations or go for StringBuilder or Streams.



No comments:

Post a Comment

Was this article useful?