String只会在一种情况下放入常量池,那就是用""修饰时。
例如
String str1 = "abc";
这个时候会把字符串"abc"放入常量池。
又或者当编译器可以确定变量的值时,如下:
String str1 = "abc" + "def";
这个时候会把字符串"abcdef"放入常量池。
所以我们得出一个结论substring返回值是不会保存在常量池中的,所以他会随着GC调用而回收
验证 public static void main(String[] args) throws InterruptedException {
String a = "123456";
String b = a.substring(3);
System.out.println(System.identityHashCode(b.intern()));
b = null;
System.gc();
b = a.substring(3);
System.out.println(System.identityHashCode(b.intern()));
b = null;
System.gc();
b = a.substring(3);
System.out.println(System.identityHashCode(b.intern()));
// 输出结果
// 1804094807
// 951007336
// 2001049719
}
2.substring返回时究竟发生了什么操作
JDK1.6中的substring
JDK1.6中String对象由以下3个成员变量组成
String(int offset, int count, char value[]) {
this.value = value;
this.offset = offset;
this.count = count;
}
value char数组
offset 偏移量
count 长度
所以在JDK1.6中substring本质上是生成一个新的String对象,但是引用的char数组是和父对象是同一个数组,只是改变了偏移量与长度
public String substring(int beginIndex, int endIndex) {
if (beginIndex 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);
}
JDK1.6中的substring中产生的问题
既然没有数组还是同一个数组,那么在回收大字符串的时候会因为剪切过的字符串还在引用,而导致无法回收,从而引起内存泄漏。这个BUG也被官方收录并在JDK1.7中得到了修正。
原创文章 47获赞 42访问量 8万+
关注
私信
展开阅读全文
作者:加班狂魔