String中substring方法内存泄漏问题
众所周知,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 = 0;
-
this.count = count;
-
this.value = Arrays.copyOfRange(value, offset, offset+count);
-
}
其中 value变量不再引用了而是重新新建了一个,所以没有这个问题了,是不是大家看完之后对这个方法有了更全新的认识?
转载请注明—作者:Java我人生(陈磊兴) 原文出处:http://blog.csdn.net/chenleixing/article/details/43646255
最后,认真看过的网友们,大神们,如有感觉我这个程序猿有哪个地方说的不对或者不妥或者你有很好的
提议或者建议或点子方法,还望您大恩大德施舍n秒的时间留下你的宝贵文字(留言),以便你,我,还有广大的程序猿们更快地成长与进步.......
String中substring方法内存泄漏问题的更多相关文章
- Android中常见的内存泄漏
为什么会产生内存泄漏? 当一个对象已经不需要再使用了,本该被回收时,而有另外一个正在使用的对象持有它的引用从而导致它不能被回收,这导致本该被回收的对象不能被回收而停留在堆内存中,这就产生了内存泄漏. ...
- JDK6和JDK7中String的substring()方法及其差异
翻译人员: 铁锚 翻译日期: 2013年11月2日 原文链接: The substring() Method in JDK 6 and JDK 7 在JDK6与JDK7这两个版本中,substri ...
- android中常见的内存泄漏和解决的方法
android中的内存溢出预计大多数人在写代码的时候都出现过,事实上突然认为工作一年和工作三年的差别是什么呢.事实上干的工作或许都一样,产品汪看到的结果也都一样,那差别就是速度和质量了. 写在前面的一 ...
- JDK6与JDK7中String类subString()方法的区别
1.subString()方法的作用 subString(int beginIndex, int endIndex)方法的返回的是以beginIndex开始到 endIndex-1结束的某个调用字符串 ...
- 菜鸟译文(三)——JDK6和JDK7中substring()方法的对比
substring(int beginIndex, int endIndex)方法在JDK6和JDK7中是不同的.了解他们的区别可以让我们更好的使用这个方法.方便起见,以下用substring() 代 ...
- .NET中常见的内存泄漏和解决办法
在.NET中,虽然CLR的GC垃圾回收器帮我们自动回收托管堆对象,释放内存,最大程度避免了"内存泄漏"(应用程序所占用的内存没有得到及时释放),但.NET应用程序"内存泄 ...
- PerfView专题 (第三篇):如何寻找 C# 中的 VirtualAlloc 内存泄漏
一:背景 上一篇我们聊到了如何用 PerfView 去侦察 NTHeap 的内存泄漏,这种内存泄漏往往是用 C 的 malloc 或者 C++ 的 new 分配而不释放所造成的,这一篇我们来聊一下由 ...
- java String 中 intern方法的概念
1. 首先String不属于8种基本数据类型,String是一个对象. 因为对象的默认值是null,所以String的默认值也是null:但它又是一种特殊的对象,有其它对象没有的一些特性. 2. ne ...
- android 中如何分析内存泄漏
转载:http://blog.csdn.net/fulinwsuafcie/article/details/8363218 前提条件: 1,电脑安装了java 运行环境 2,手机端开启了 USB 调试 ...
随机推荐
- 关于js盒子模型的知识梳理
盒子模型 JS盒子模型中的13个常用属性: clientWidth/clientHeight:可视区域的宽高,宽高+PADDING组成 clientTop/clientLeft:上边框和左边框的宽度 ...
- Spring拦截器和Servlet过滤器区别
http://blog.csdn.net/chenleixing/article/details/44573495
- js进阶 12-14 jquery的事件触发函数是哪两个
js进阶 12-14 jquery的事件触发函数是哪两个 一.总结 一句话总结:trigger和triggerHandler 1.trigger传额外参数时候的注意事项是什么? 注意样例中是三个参数 ...
- windows+python3+opencv3.4安装
1.安装anaconda. 2.pip install opencv-python 网上很多关于python opencv安装说明,步骤极其繁琐,其实按照本说明只需两步就可安装完成.
- IOS计算两点之间的距离
//广州经纬度 CLLocationCoordinate2D guangZhouLocation; guangZhouLocation.latitude = 23.20; guangZhouLocat ...
- [TypeScript] Interface and Class
When to use Interface and when to use Class. Let's see one example: export interface Lesson { course ...
- SetForegroundWindow的正确用法
在SetForegroundWindow之前比较早的时候(比如main函数里)调用一下以下代码: DWORD dwTimeout = -1; SystemParametersInfo(SPI_GETF ...
- iOS开发RunLoop学习:三:Runloop相关类(source和Observer)
一:RunLoop相关类: 其中:source0指的是非基于端口por,说白了也就是处理触摸事件,selector事件,source1指的是基于端口的port:是处理系统的一些事件 注意:创建一个Ru ...
- iOS开发之Quartz2D 六 绘制UIImageView
#import <UIKit/UIKit.h> @interface XMGImageView : UIView /** <#注释#> */ @property (nonato ...
- HttpClient基础教程 分类: C_OHTERS 2014-05-18 23:23 2600人阅读 评论(0) 收藏
1.HttpClient相关的重要资料 官方网站:http://hc.apache.org/ API:http://hc.apache.org/httpcomponents-client-4.3.x/ ...