Java String.substring方法潜在的内存泄漏?

时间:2013-01-04 16:34:55

标签: java string memory-leaks

我正在浏览String类API,看起来像substring方法导致潜在的内存泄漏,因为它与原始String共享相同的字符数组。

如果原始字符串很大,那么substring返回的小字符串可以防止原始字符串(由大数组备份)从Java中的垃圾收集。

有任何想法或者我读错了API。

3 个答案:

答案 0 :(得分:18)

存在内存泄漏的可能性,如果你获取一个相当大的字符串的子字符串而不是复制(通常是通过String(String)构造函数)。

请注意,自Java 7u6以来,这已发生变化。 请参阅http://bugs.sun.com/view_bug.do?bug_id=4513622

实施flyweight patternString对象周围的原始假设不再被视为有效。

有关详细信息,请参阅this answer

答案 1 :(得分:4)

  1. 直到Java 7u6就是这种情况 - 你通常会这样做:

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

    这有效地消除了依赖关系,原始字符串现在可用于GC。这是使用字符串构造函数的唯一场景之一。

  2. Java 7u6开始,创建了一个新的String,并且不再存在内存问题。

答案 2 :(得分:1)

在Java 7中,String的子串被修改为:

/**
     * 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);
    }

因此,每次使用beginIndex不等于0的subString时,我们都会有新的String对象。