内存泄露之--JDK6里的subString()方法
源码品读心得:
JDK6
String(int offset, int charCount, char[] chars) {
this.value = chars;
this.offset = offset;
this.count = charCount;
}
public String substring(int start, int end) {
if (start == 0 && end == count) {
return this;
}
// Fast range check.
if (start >= 0 && start <= end && end <= count) {
return new String(offset + start, end - start, value);
}
throw startEndAndLength(start, end);
}
如何一个很长的字符串调用了subString方法,String对象中实际的保存的字符串不会改变( this.value = chars;),只是根据offset和charCount来读取其中的一部分,
如果我们只想使用其中截取出来的字符串,这样就导致GC无法回收该内存。
优点:多次截取和同时想用改字符串不会导致多次创建内存
缺点:如果只想使用截取的一小部分字符串,则会导致内存浪费也容易使GC无法回收该内存,导致内存泄露
JDK7
增加了以下方法
public String(char[] data, int offset, int charCount) {
if ((offset | charCount) < 0 || charCount > data.length - offset) {
throw failedBoundsCheck(data.length, offset, charCount);
}
this.offset = 0;
this.value = new char[charCount];
this.count = charCount;
System.arraycopy(data, offset, value, 0, count);
优点:如果只想使用截取的一小部分字符串,这样可以让GC回收这过大的字符串
缺点:每次截取都要开辟新的内存
源码品读心得:
JDK6
String(int offset, int charCount, char[] chars) {
this.value = chars;
this.offset = offset;
this.count = charCount;
}
public String substring(int start, int end) {
if (start == 0 && end == count) {
return this;
}
// Fast range check.
if (start >= 0 && start <= end && end <= count) {
return new String(offset + start, end - start, value);
}
throw startEndAndLength(start, end);
}
如何一个很长的字符串调用了subString方法,String对象中实际的保存的字符串不会改变( this.value = chars;),只是根据offset和charCount来读取其中的一部分,
如果我们只想使用其中截取出来的字符串,这样就导致GC无法回收该内存。
优点:多次截取和同时想用改字符串不会导致多次创建内存
缺点:如果只想使用截取的一小部分字符串,则会导致内存浪费也容易使GC无法回收该内存,导致内存泄露
JDK7
增加了以下方法
public String(char[] data, int offset, int charCount) {
if ((offset | charCount) < 0 || charCount > data.length - offset) {
throw failedBoundsCheck(data.length, offset, charCount);
}
this.offset = 0;
this.value = new char[charCount];
this.count = charCount;
System.arraycopy(data, offset, value, 0, count);
}
通过以上方法可以根据offset和charCount来真正修改内存中的String值优点:如果只想使用截取的一小部分字符串,这样可以让GC回收这过大的字符串
缺点:每次截取都要开辟新的内存
总结:个人觉得大家一致说的JDK6中subString内存泄露有点太偏向了,JDK7添加了一个新的构造方法来让我们根据使用场景选择使用。
以上个人观习JDK6与JDK7得出的观点,有错误欢迎指出。