论坛首页 Java企业应用论坛

优化变成了忧患:String类的split方法引起的内存泄漏

浏览 53054 次
该帖已经被评为精华帖
作者 正文
   发表时间:2010-03-29  
BTW, 楼主的标题也非常贴切, 大家再仔细审读一下楼主的标题, 真棒, 精华贴, 错不了
0 请登录后投票
   发表时间:2010-03-29  
关键是 new String() 会重新创建一个对象.
0 请登录后投票
   发表时间:2010-03-29  
split或者substring出来另外存放,这种情况太常见了。以前分析用java分析html代码与同事发现过这问题。debug出来子串,怎么打印都是正确的,可是elipse的调试器里展示的内存却是整个html。一直以为是调试器的问题。今天终于明白了,感谢lz!
0 请登录后投票
   发表时间:2010-03-29  
用intern()应该比拷贝构造更好
0 请登录后投票
   发表时间:2010-03-29  
这个过去注意到过,一个老外提过这个问题

http://eyalsch.wordpress.com/2009/10/27/stringleaks/
0 请登录后投票
   发表时间:2010-03-29  
StringBuffer,StringBuilder,lz能不能也帮看看subString方法有无这问题?我目前在搞j2me,j2me的StringBuffer是没有subString方法的,j2me是没StringBuilder的。
0 请登录后投票
   发表时间:2010-03-29  
鸟哥哥 写道
StringBuffer,StringBuilder,lz能不能也帮看看subString方法有无这问题?我目前在搞j2me,j2me的StringBuffer是没有subString方法的,j2me是没StringBuilder的。

经查看,也是有这问题,呵呵。
0 请登录后投票
   发表时间:2010-03-29  
鸟哥哥 写道
StringBuffer,StringBuilder,lz能不能也帮看看subString方法有无这问题?我目前在搞j2me,j2me的StringBuffer是没有subString方法的,j2me是没StringBuilder的。


看了JDK6的StringBuffer和StringBuilder。它们没有split方法,但是有subString方法。它们的subString没有本文提到的问题,原因可以看他们的代码,在父类AbstractStringBuilder中。
 public String substring(int start, int end) {
        if (start < 0)
	    throw new StringIndexOutOfBoundsException(start);
	if (end > count)
	    throw new StringIndexOutOfBoundsException(end);
	if (start > end)
	    throw new StringIndexOutOfBoundsException(end - start);
        return new String(value, start, end - start);
}


subString最终还是调用了String的构造函数,该构造函数拷贝了char[],因此是安全的。
public String(char value[], int offset, int count) {
        if (offset < 0) {
            throw new StringIndexOutOfBoundsException(offset);
        }
        if (count < 0) {
            throw new StringIndexOutOfBoundsException(count);
        }
        // Note: offset or count might be near -1>>>1.
        if (offset > value.length - count) {
            throw new StringIndexOutOfBoundsException(offset + count);
        }
        this.offset = 0;
        this.count = count;
        this.value = Arrays.copyOfRange(value, offset, offset+count);
    }


而String类的subString调用的是另一个版本String构造函数,该构造函数对于外部类(AbstractStringBuilder)是不可见的。
// 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;
    }


从该构造函数的访问权限和注释,我们都可以看出,SUN为了优化性能而专门写了这个函数。
0 请登录后投票
   发表时间:2010-03-29  
学习了,没想到常用的字符串还有这样的问题
0 请登录后投票
   发表时间:2010-03-29  
插个话:楼主怎么会传进一个几百K的字符串再切分的?觉得这场景很特别。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics