16

我正在通过 String 类 API 并且看起来存在由 substring 方法引起的潜在内存泄漏,因为它与原始 String 共享相同的字符数组。

如果原始字符串很大,则子字符串返回的小字符串可以防止原始字符串(由大数组备份)在 Java 中进行垃圾回收。

任何想法或我是否读错了 API。

4

3 回答 3

20

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

请注意,自Java 7u6以来,这已经发生了变化。请参阅https://bugs.openjdk.java.net/browse/JDK-7197183

String围绕实现享元模式的对象的原始假设不再被视为有效。

有关更多信息,请参阅此答案

于 2013-01-04T16:36:23.067 回答
4
  1. 在 Java 7u6 之前就是这种情况 - 您通常会通过以下方式处理该问题:

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

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

  2. Java 7u6 开始,创建了一个新字符串,不再存在内存问题。

于 2013-01-04T16:43:06.257 回答
1

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

/**
     * 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 对象。

于 2015-10-09T11:54:19.603 回答