Monday, 25 April 2016

What is the memory leak problem with substring() till Java 1.6 ?


In String implementation till JDK 1.6,
  • String is stored as char array
  • Private variables (offset and count) are used to manage the char array

private final char value[];
/** offset = First index of the storage
private final int offset;
/** count = Number of characters in the String
private final int count;
...
...
public String substring(int beginIndex, int endIndex) {
   //check boundary
   return ((beginIndex == 0) && (endIndex == count))? this :
  new String(offset + beginIndex, endIndex - beginIndex, value);
}

String(int offset, int count, char value[]) {
   this.value = value;
   this.offset = offset;
   this.count = count;
}

On calling substring() , iassigns the new values of offset and count variables every time.


Memory leak problem till JDK 1.6

If you have a very long string but only need a small part by using substring() method will return the offset and count which refers the original string array which will not permit to garbage collection of original string array.

This will cause a performance problem, since we need only a small part and keeping the whole char value[] array in memory (No garbage collection).


How programmer can resolve this issue in JDK 1.6 ?

subString = string.substring(3, 10) "";

In your code, string.substring(3, 10) will return the substring which point to original string array and the substring will not allow the garbage collection for old string (char value[]).

But when we add the empty string to offset, new string will form in constant pool with new char value[] array.
By this way, we can overcome the problem of garbage collection of old string array.




How it has been resolved in JDK 1.7 ?

This problem is fixed by returning the new copy of character array.

public String substring(int beginIndex, int endIndex) {
    // Check boundary
    int subLen = endIndex - beginIndex;
    return new String(value, beginIndex, subLen);

}

public String(char value[], int offset, int count) {
    // Check boundary
    ...
    // It return new copy on array.
    this.value = Arrays.copyOfRange(value, offset, offset + count);
}

No comments:

Post a Comment

Note: only a member of this blog may post a comment.