转载自   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 offsetint 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 使用不当可能导致内存泄露相关推荐

  1. 使用ThreadLocal不当可能会导致内存泄露

    使用ThreadLocal不当可能会导致内存泄露 基础篇已经讲解了ThreadLocal的原理,本节着重来讲解下使用ThreadLocal会导致内存泄露的原因,并讲解使用ThreadLocal导致内存 ...

  2. inputstreamreader未关闭会导致oom_ThreadLocal 一定会导致内存泄露?

    在面试的时候,ThreadLocal作为高并发常用工具经常会被问到.而面试官比较喜欢问的问题有以下两个: 1.ThreadLocal是怎么实现来保证每个线程的变量副本的. 2.ThreadLocal的 ...

  3. Java内存泄漏系列--匿名内部类导致内存泄露--原因/解决方案

    原文网址:Java内存泄漏系列--匿名内部类导致内存泄露--原因/解决方案_IT利刃出鞘的博客-CSDN博客 简介 说明 本文用示例介绍匿名内部类会导致内存泄漏的原因及其解决方案. 相关网址 普通内部 ...

  4. Java内存泄露系列--内部类持有外部类导致内存泄露--原因/解决方案

    原文网址:Java内存泄露系列--内部类持有外部类导致内存泄露--原因/解决方案_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Java内部类持有外部类导致内存泄露的原因以及其解决方案. 为什么内部 ...

  5. NSTimer 增加引用计数, 导致内存泄露,

    NSTimer 增加引用计数, 导致内存泄露, self.adTimer   = [NSTimerscheduledTimerWithTimeInterval:5.0target:selfselect ...

  6. VC 2010的MFC函数,CMFCVisualManager::GetInstance()可能导致内存泄露

    今天在网上看到一篇文章,关于CMFCVisualManager的内存泄露问题( 链接是 http://zhanyonhu.blog.163.com/blog/static/16186044201132 ...

  7. pthread_create会导致内存泄露

    这几天一直在调试一个系统,系统的功能就是定时发送数据.接收数据然后解析收到的数据,转换成一定的格式存入数据库中.我为了并发操作,所以每接收到一个数据包,就调用pthread_create函数创建一个默 ...

  8. android弹出输入法内存,android 输入法导致内存泄露问题

    该方法侵入太高,必须重新EditText,如果我们直接使用一个第三方的控件包含了EditText,那么这么做就没有意义,所以放弃了这种方案,然后我又想出了其他方案,Android 输入法导致内存泄露以 ...

  9. terminatethread导致内存泄露

    terminatethread导致内存泄露,waitforsingleobject又容易导致UI卡死,真头疼 听过无数次不要TerminateThread,只是工作中常用,貌似也没有什么问题.今天在高 ...

最新文章

  1. Servlet 获取IllegelStateException
  2. Docker容器管理总结
  3. 新学语言python和JS
  4. c语言的简单题目,C语言的一些简单题目,没有答案,哪位大神帮忙做一下!!!...
  5. 5界面怎么做窗帘拉动的效果_别让土味窗帘毁了你的家
  6. android开发 eclipse alt+”/”自动提示失效
  7. 2.9.JavaScript--内置对象
  8. eclipse+tomcat开发web程序
  9. 响应式web之@media screen
  10. mrc20温控f1什么意思_精确率、召回率、F1 值、ROC、AUC 各自的优缺点是什么?
  11. linux ubuntu系统远程连接linux ubuntu
  12. 机器学习--文本分析(jieba)
  13. 【VueElementUI学习】表格序号
  14. 【Beta】 第二次Daily Scrum Meeting
  15. vue2中取消严格检查模式/关闭语法检查
  16. oracle的路由器,如何充分使用Oracle?
  17. layout_gravity和gravity的区分和应用
  18. Hexo-域名设置+收录
  19. 解决Partially written block xxx being set for retirement(dm365)
  20. DL4J的矩阵处理模块ND4J的常用函数整理

热门文章

  1. leetcode435. 无重叠区间
  2. 地理生物高考成绩查询2021,2021北京中考地理生物成绩查询时间【已公布】
  3. [设计模式]模板方法模式
  4. python中开关_pyq中的开关按钮
  5. linux关机方法有哪些?有何区别_Linux下判断是否正常关机的一个简单方法
  6. 递归算法(一)递归概念与思路
  7. Spring Cloud——Consul——架构体系
  8. newcode Islands 思维
  9. B Convex Polygon
  10. 牛客网【每日一题】4月2日 月月查华华的手机