Подтвердить что ты не робот

Устранение утечки памяти в методе Java String.substring?

Я проходил через API класса String и выглядел как потенциальная утечка памяти, вызванная методом подстроки, поскольку она разделяет тот же массив символов, что и исходный String.

Если исходная строка огромна, то маленькая строка, возвращаемая подстрокой, может помешать исходной строке (подкрепленной большим массивом) из коллекции мусора в Java.

Любые мысли или я неправильно прочитал API.

4b9b3361

Ответ 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.