7.Java中的subString()真的会引起内存泄露么?
答:这里首先有个问题,什么是内存泄露,那就向讲一讲内存溢出和内存泄漏的含义,所谓的内存溢出呢,就上内存不够用了,比如在一个无限的循环里不断的创建一个大的对象,使得沾满内存溢出,这就是所谓的内存溢出;而内存泄漏呢,就上指为一个对象分配好内存之后,在对象已经不再使用时未及时的释放,倒是一直占据内存单元,使实际可用内存减少,就好像内存泄漏了一样。内存泄漏问题其实就是在JDK1.6中,例如有一个字符串a,然后字符串b是字符串a的一个子字符串,就上使用substring()截取,这样的话a和b用的value是同一个引用,如果我们把a的引用为空,本意是释放a所占用的空间,但是这个时候,垃圾回收机制是没办法回收这个value的,因为这个还在被字符串b所引用,所以就会一直占着堆内存,就会导致内存泄漏。
注
解是这么解的,但是要注意这是jdk1.6之前的会产生的,在jdk1.8上不会产生这个问题,原因在与源码的改变。
原先subString源码:
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > count) {
throw new StringIndexOutOfBoundsException(endIndex);
}
if (beginIndex > endIndex) {
throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
}
return ((beginIndex == 0) && (endIndex == count)) ? this :
new String(offset + beginIndex, endIndex - beginIndex, value);
}
// Package private constructor which shares value array for speed.
String(int offset, int count, char value[]) {
this.value = value;
this.offset = offset;
this.count = count;
}
JDK1.8时,subString()源码,已经不在引用原来的char[]数组,而是建立了新的数组。
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > value.length) {
throw new StringIndexOutOfBoundsException(endIndex);
}
int subLen = endIndex - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return ((beginIndex == 0) && (endIndex == value.length)) ? this
: new String(value, beginIndex, subLen);
}
public String(char value[], int offset, int count) {
if (offset < 0) {
throw new StringIndexOutOfBoundsException(offset);
}
if (count <= 0) {
if (count < 0) {
throw new StringIndexOutOfBoundsException(count);
}
if (offset <= value.length) {
this.value = "".value;
return;
}
}
// Note: offset or count might be near -1>>>1.
if (offset > value.length - count) {
throw new StringIndexOutOfBoundsException(offset + count);
}
this.value = Arrays.copyOfRange(value, offset, offset+count);
}
public static char[] copyOfRange(char[] original, int from, int to) {
int newLength = to - from;
if (newLength < 0)
throw new IllegalArgumentException(from + " > " + to);
char[] copy = new char[newLength];
System.arraycopy(original, from, copy, 0,
Math.min(original.length - from, newLength));
return copy;
}