Troubleshoot memory leak in Java method String.substring?

I went through the String class API and looked like a potential memory leak caused by the substring method, since it shares the same character array as the original String.

If the source string is huge, then the small string returned by the substring may interfere with the original string (backed by a large array) from the garbage collection in Java.

Any thoughts or I read the API incorrectly.

+14
java string memory-leaks
Jan 04 '13 at
source share
3 answers

There is a chance of a memory leak if you take a substring of a meaningful string and do not create a copy (usually through the constructor String(String) ).

Please note that this has changed since Java 7u6 . See http://bugs.sun.com/view_bug.do?bug_id=4513622 .

The original assumptions around the String object that implement the flyweight pattern are no longer considered valid.

See this answer for more information.

+17
Jan 04 '13 at
source share
  • This was the case when Java 7u6 - you usually deal with the problem by doing:

     String sub = new String(s.substring(...)); // create a new string 

    This effectively removes the dependency, and the source string is now available for the GC. This, by the way, is one of the only scenarios where using the string constructor makes sense.

  • Since Java 7u6 , a new String is created and there is no longer a memory issue.

+4
Jan 04 '13 at 16:43
source share

In Java 7, the string substring changes to:

 /** * Returns a new string that is a substring of this string. The * substring begins with the character at the specified index and * extends to the end of this string. <p> * Examples: * <blockquote><pre> * "unhappy".substring(2) returns "happy" * "Harbison".substring(3) returns "bison" * "emptiness".substring(9) returns "" (an empty string) * </pre></blockquote> * * @param beginIndex the beginning index, inclusive. * @return the specified substring. * @exception IndexOutOfBoundsException if * <code>beginIndex</code> is negative or larger than the * length of this <code>String</code> object. */ public String substring(int beginIndex) { if (beginIndex < 0) { throw new StringIndexOutOfBoundsException(beginIndex); } int subLen = value.length - beginIndex; if (subLen < 0) { throw new StringIndexOutOfBoundsException(subLen); } return (beginIndex == 0) ? this : new String(value, beginIndex, subLen); } 

Therefore, every time you execute a subString with beginIndex NOT equal to 0, we have a new String object.

0
09 Oct '15 at 11:54 on
source share



All Articles