Устранение утечки памяти в методе Java String.substring?
Я проходил через API класса String и выглядел как потенциальная утечка памяти, вызванная методом подстроки, поскольку она разделяет тот же массив символов, что и исходный String.
Если исходная строка огромна, то маленькая строка, возвращаемая подстрокой, может помешать исходной строке (подкрепленной большим массивом) из коллекции мусора в Java.
Любые мысли или я неправильно прочитал API.
Ответы
Ответ 1
Существует вероятность утечки памяти, если вы берете подстроку значимой строки и не создаете копию (обычно через конструктор String(String)
).
Обратите внимание, что это изменилось с Java 7u6.
См. http://bugs.sun.com/view_bug.do?bug_id=4513622.
Исходные предположения вокруг объекта String
, реализующие flyweight pattern, больше не считаются действительными.
Для получения дополнительной информации см. этот ответ.
Ответ 2
-
Это был случай, когда Java 7u6 - вы, как правило, справляетесь с проблемой, делая:
String sub = new String(s.substring(...)); // create a new string
Это эффективно удаляет зависимость, и исходная строка теперь доступна для GC. Это, кстати, один из единственных сценариев, где использование конструктора строк имеет смысл.
-
Поскольку Java 7u6, создается новая String и больше не возникает проблема с памятью.
Ответ 3
В Java 7 строковая подстрока изменяется на:
/**
* 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);
}
Следовательно, каждый раз, когда вы выполняете subString с beginIndex NOT, равным 0, у нас есть новый объект String.