String中substring方法内存泄漏问题
来源:互联网 发布:软件开发电脑配置 编辑:程序博客网 时间:2024/05/18 22:54
众所周知,JDK中以前String类中的substring方法存在内存泄漏问题,之所以说是以前,是因为JDK1.7及以后的版本已经修复了,我看都说JDK1.6的版本也存在这个问题,但是我本机上安装的1.6看了看源码不存在内存泄漏问题啊,又看了1.7的源码,和我本机的1.6的一样,是不是我的1.6版版其实是1.7的?!唉,不管了,反正1.7版本肯定没有这个问题(1.5及更老版本肯定有)了,大家就放心的用吧。
之所以存在内存泄漏的问题,是因为原先的版本中,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); }而其中用到的String构造方法是这样的:
// 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; }this.value=value这种实现就出现问题了,因为String类中有几个私有的成员变量:
/** The value is used for character storage. */ private final char value[]; /** The offset is the first index of the storage that is used. */ private final int offset; /** The count is the number of characters in the String. */ private final int count; /** Cache the hash code for the string */ private int hash; // Default to 0明白了吧,这种实现还在引用着原先字符串变量的value[],通过offset和count返回一个长得像的“截取”后的字符串给人一种错觉,导致JVM认为这个最初字符串还在被引用着不对其gc,不过之所以这么做SUN公司(oracle 10年收购了)的JDK编写人员也是有原因的,就是效率问题,如注释所说:
Package private constructor which shares value array for speed.
这样导致的后果就是如果有一个很大很长的字符串我只需要其中的一小部分字符串用substring实现的话,如果让你看似得到的“新”的短小字符串一直没被JVM 回收的话,那么相当这个最初的大字符串也没被回收,尤其是你把这个短小“新”的字符串直接以引用的形式付给一个静态的全局变量,在加上如果访问数量很大,那应该“代价”还是蛮可观的,不过可以简单的这样new(s.substring())就避免了这个问题。
新的JDK中substring之所以不存在这个问题了,是因为这个构造方法改成这样了:
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 = offset; this.count = count; this.value = Arrays.copyOfRange(value, offset, offset+count); }
其中 value变量不再引用了而是重新新建了一个,所以没有这个问题了,是不是大家看完之后对这个方法有了更全新的认识?
转载请注明—作者:Java我人生(陈磊兴) 原文出处:http://blog.csdn.net/chenleixing/article/details/43646255
- String中substring方法内存泄漏问题
- String中substring方法内存泄漏问题
- String中substring方法内存泄漏问题
- String中substring方法内存泄漏问题
- String中substring方法内存泄漏问题
- String类substring方法导致的Java内存泄漏问题
- String类substring方法导致的Java内存泄漏问题
- String类substring方法导致的Java内存泄漏问题
- Java中由substring方法引发的内存泄漏
- Java中由substring方法引发的内存泄漏
- Java中由substring方法引发的内存泄漏
- Java中由substring方法引发的内存泄漏
- Java中由substring方法引发的内存泄漏
- Java中由substring方法引发的内存泄漏
- Java中由substring方法引发的内存泄漏
- set方法中内存泄漏问题
- Java中,String的subString方法易导致内存溢出
- java6 substring() 内存泄漏
- eclipse上配置tomcat
- 微信小程序组件
- windows下electron安装问题一则
- ubuntu16上传文件到服务器
- flask 调试模式自动加载修改后代码
- String中substring方法内存泄漏问题
- Linux从入门到无法自拔
- 如何将多sheet Excel 导入到超级表格中
- opengl卡通渲染之逐顶点渲染与逐像素渲染
- 第三届讯飞测试技术嘉年华视频上线
- KMP基本模板理解
- day25之布隆过滤器的实现和优缺点以及扩展
- 浅析Spring事务传播行为和隔离级别
- [C++] 右值引用:移动语义与完美转发