String 使用不当可能导致内存泄露
转载自 String 使用不当可能导致内存泄露
String是Java中一个比较基础的类,每一个开发人员都会经常接触到。而且,String也是面试中经常会考的知识点。String有很多方法,有些方法比较常用,有些方法不太常用。
今天介绍一个String使用不当可能导致内存泄露的问题,主要围绕其subString方法。围绕String和subString也有很多面试题,是比较重要的知识点。
substring(int beginIndex, int endIndex)
方法在不同版本的JDK中的实现是不同的。了解他们的区别可以帮助你更好的使用他。为简单起见,后文中用substring()
代表substring(int beginIndex, int endIndex)
方法。
substring() 的作用
substring(int beginIndex, int endIndex)
方法截取字符串并返回其[beginIndex,endIndex-1]范围内的内容。
String x = "abcdef";
x = x.substring(1,3);
System.out.println(x);
输出内容:
bc
调用substring()时发生了什么?
你可能知道,因为x是不可变的,当使用x.substring(1,3)
对x赋值的时候,它会指向一个全新的字符串:
然而,这个图不是完全正确的表示堆中发生的事情。因为在jdk6 和 jdk7中调用substring时发生的事情并不一样。
JDK 6中的substring
String是通过字符数组实现的。在jdk 6 中,String类包含三个成员变量:char value[]
, int offset
,int count
。他们分别用来存储真正的字符数组,数组的第一个位置索引以及字符串中包含的字符个数。
当调用substring方法的时候,会创建一个新的string对象,但是这个string的值仍然指向堆中的同一个字符数组。这两个对象中只有count和offset 的值是不同的。
下面是证明上说观点的Java源码中的关键代码:
//JDK 6
String(int offset, int count, char value[]) {this.value = value;this.offset = offset;this.count = count;
}public String substring(int beginIndex, int endIndex) {//check boundaryreturn new String(offset + beginIndex, endIndex - beginIndex, value);
}
substring与内存泄露
如果你有一个很长很长的字符串,但是当你使用substring进行切割的时候你只需要很短的一段。
这可能导致性能问题,因为你需要的只是一小段字符序列,但是你却引用了整个字符串(因为这个非常长的字符数组一直在被引用,所以无法被回收,就可能导致内存泄露)。
在JDK 6中,一般用以下方式来解决该问题,原理其实就是生成一个新的字符串并引用他。
x = x.substring(x, y) + ""
关于JDK 6中subString的使用不当会导致内存系列已经被官方记录在Java Bug Database中:
内存泄露:在计算机科学中,内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存。 内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费。
JDK 7 中的substring
上面提到的问题,在jdk 7中得到解决。在jdk 7 中,substring方法会在堆内存中创建一个新的数组。
Java源码中关于这部分的主要代码如下:
//JDK 7
public String(char value[], int offset, int count) {//check boundarythis.value = Arrays.copyOfRange(value, offset, offset + count);
}public String substring(int beginIndex, int endIndex) {//check boundaryint subLen = endIndex - beginIndex;return new String(value, beginIndex, subLen);
}
以上是JDK 7中的subString方法,其使用new String
创建了一个新字符串,避免对老字符串的引用。从而解决了内存泄露问题。
所以,如果你的生产环境中使用的JDK版本小于1.7,当你使用String的subString方法时一定要注意,避免内存泄露。
String 使用不当可能导致内存泄露相关推荐
- 使用ThreadLocal不当可能会导致内存泄露
使用ThreadLocal不当可能会导致内存泄露 基础篇已经讲解了ThreadLocal的原理,本节着重来讲解下使用ThreadLocal会导致内存泄露的原因,并讲解使用ThreadLocal导致内存 ...
- inputstreamreader未关闭会导致oom_ThreadLocal 一定会导致内存泄露?
在面试的时候,ThreadLocal作为高并发常用工具经常会被问到.而面试官比较喜欢问的问题有以下两个: 1.ThreadLocal是怎么实现来保证每个线程的变量副本的. 2.ThreadLocal的 ...
- Java内存泄漏系列--匿名内部类导致内存泄露--原因/解决方案
原文网址:Java内存泄漏系列--匿名内部类导致内存泄露--原因/解决方案_IT利刃出鞘的博客-CSDN博客 简介 说明 本文用示例介绍匿名内部类会导致内存泄漏的原因及其解决方案. 相关网址 普通内部 ...
- Java内存泄露系列--内部类持有外部类导致内存泄露--原因/解决方案
原文网址:Java内存泄露系列--内部类持有外部类导致内存泄露--原因/解决方案_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Java内部类持有外部类导致内存泄露的原因以及其解决方案. 为什么内部 ...
- NSTimer 增加引用计数, 导致内存泄露,
NSTimer 增加引用计数, 导致内存泄露, self.adTimer = [NSTimerscheduledTimerWithTimeInterval:5.0target:selfselect ...
- VC 2010的MFC函数,CMFCVisualManager::GetInstance()可能导致内存泄露
今天在网上看到一篇文章,关于CMFCVisualManager的内存泄露问题( 链接是 http://zhanyonhu.blog.163.com/blog/static/16186044201132 ...
- pthread_create会导致内存泄露
这几天一直在调试一个系统,系统的功能就是定时发送数据.接收数据然后解析收到的数据,转换成一定的格式存入数据库中.我为了并发操作,所以每接收到一个数据包,就调用pthread_create函数创建一个默 ...
- android弹出输入法内存,android 输入法导致内存泄露问题
该方法侵入太高,必须重新EditText,如果我们直接使用一个第三方的控件包含了EditText,那么这么做就没有意义,所以放弃了这种方案,然后我又想出了其他方案,Android 输入法导致内存泄露以 ...
- terminatethread导致内存泄露
terminatethread导致内存泄露,waitforsingleobject又容易导致UI卡死,真头疼 听过无数次不要TerminateThread,只是工作中常用,貌似也没有什么问题.今天在高 ...
最新文章
- Servlet 获取IllegelStateException
- Docker容器管理总结
- 新学语言python和JS
- c语言的简单题目,C语言的一些简单题目,没有答案,哪位大神帮忙做一下!!!...
- 5界面怎么做窗帘拉动的效果_别让土味窗帘毁了你的家
- android开发 eclipse alt+”/”自动提示失效
- 2.9.JavaScript--内置对象
- eclipse+tomcat开发web程序
- 响应式web之@media screen
- mrc20温控f1什么意思_精确率、召回率、F1 值、ROC、AUC 各自的优缺点是什么?
- linux ubuntu系统远程连接linux ubuntu
- 机器学习--文本分析(jieba)
- 【VueElementUI学习】表格序号
- 【Beta】 第二次Daily Scrum Meeting
- vue2中取消严格检查模式/关闭语法检查
- oracle的路由器,如何充分使用Oracle?
- layout_gravity和gravity的区分和应用
- Hexo-域名设置+收录
- 解决Partially written block xxx being set for retirement(dm365)
- DL4J的矩阵处理模块ND4J的常用函数整理