我正在浏览String类API,看起来像substring方法导致潜在的内存泄漏,因为它与原始String共享相同的字符数组。
如果原始字符串很大,那么substring返回的小字符串可以防止原始字符串(由大数组备份)从Java中的垃圾收集。
有任何想法或者我读错了API。
答案 0 :(得分:18)
存在内存泄漏的可能性,如果你获取一个相当大的字符串的子字符串而不是复制(通常是通过String(String)
构造函数)。
请注意,自Java 7u6以来,这已发生变化。 请参阅http://bugs.sun.com/view_bug.do?bug_id=4513622。
实施flyweight pattern的String
对象周围的原始假设不再被视为有效。
有关详细信息,请参阅this answer。
答案 1 :(得分:4)
直到Java 7u6就是这种情况 - 你通常会这样做:
String sub = new String(s.substring(...)); // create a new string
这有效地消除了依赖关系,原始字符串现在可用于GC。这是使用字符串构造函数的唯一场景之一。
从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对象。