subString()造成内存泄露

subString() 泄露原因

在java程序性能优化一书中看到自己常用的方法竟然会内存泄露,马上记录下来。

1. 字符串操作中截取字符串是常用的操作,在java中,String类提供了两个截取字符串的方法:

public String subString(int beginIndex);
public String subString(int beginIndex,int endIndex)

用第二个方法来分析造成内存泄露的原因

public String subString(int beginIndex,int endIndex){
    if(beginIndex < 0){
        throw new StringIndexOutOfBoundException(beginIndex);
    }
    if(endIndex >count){//String对象可以认为是char数组的延伸和进一步封装,这里的count指字符串长度
        throw new StringIndexOutOfBoundException(endIndex);
    }
    if(beginIndex > endIndex){
        throw new StringIdexOutOfBoundException(endIndex-beginIndex);
    }
return ((beginIndex==0)&&(endIndex==count))?this: new String(offset+beginIndex,endIndex-beginIndex,value);
}
//被调用的String 的构造对象参数有偏移量,长度和char数组
String (int offset,int count,char value[]){
this.value = value;
this.offset = offset;
this.value = value;
}

在源码注释中说明,这是一个包作用域的构造函数,其目的是为了高效且快速的共享String内的char数组对象,但在这种通过偏移量截取字符串的方法,String的原生内容value被复制到子字符串中,如果,截取的原生字符串很长,但截取内容很短,在截取出来的子字符串中包含原生字符串所有内容,并占有一定的内存空间。这样实际提高了运算速度却浪费了内存空间。

解决subString 内存泄露问题

书中举了一个例子来说明

public static void main(String args[]){
    List<String> handler = new ArrayList<String>();
    for(int i =0;i<100;i++){
        HugeStr h = new HugeStr(); //此方法不到1000次就内存溢出
      //ImprovedHugeStr h = new ImprovedHugeStr();
        handler.add(h.getSubString(1,5));
    }
}

static class HugeStr{
    private String str = new String(new char[100000]);
    public String getSubString(int begin,int end){
        return str.subString(begin,end);
    }
}

static class ImproveHugeStr{
    private String str = new String(new char[100000]);
    public String getSubString(int begin,int end){
        return new String(str.subString(begin,end));
    }
}

ImproveHugeStr方法能够很好工作的关键是因为它使用了没有内存泄露的String构造函数重新生成了String对象,使得由subString方法返回的存在内存泄露问题的String对象失去所有的强引用,从而被垃圾回收器识别为垃圾对象回收,保证了系统内存的稳定

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值