`

String类substring方法导致的Java内存泄漏问题 (转)

    博客分类:
  • java
 
阅读更多

 

此问题在项目中被发现,经查看JDK源码(JDK1.6),String类的public String substring(int beginIndex, int endIndex)的实现让我很意外。

想重现这个场景很容易,请看代码。

 

 

 

 

执行此代码结果:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

 

问题就出在Huge类的 getSubString 方法,它调用了String类的substring方法。

来让我们看看 substring 类的实现吧,JDK源码如下:

 

    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);
    }
 

 

 

再让我们接下来看看 new String(offset + beginIndex, endIndex - beginIndex, value); 的实现:

 

    // 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;
    }
  

char[] value 数组被共享了。

 

在我们的main函数里的循环中,每循环一次后,我们希望Huge对象被回收,且释放它占有的内存。

但实际上 private String str = new String(new char[100000]); 占有的内存并不会被释放。

因为 我们通过 Huge 类的 getSubString 方法得到的 String 对象还存在(存在于handler的列表中),

它虽然是 length 只有 4 的对象,却享有着 char[100000] 的空间。

 

解决方案:

可以修改Huge 类的 getSubString 方法如下:

 

    public String getSubString(int begin, int end) {
        return new String(str.substring(begin, end));
    }
 

 

只要再套一个String的构造方法即可。

 

至于为什么,看看JDK源码,一看便知了。这里就不贴出来了。

分享到:
评论

相关推荐

    Java中由substring方法引发的内存泄漏详解

    Java 中的 substring 方法是一个非常常用的字符串操作方法,但是在 JDK 1.6 中,如果不当使用该方法,可能会导致严重的内存泄漏问题。下面我们将详细介绍 Java 中由 substring 方法引发的内存泄漏问题的原因和解决...

    Java substring方法实现原理解析

    在 JDK 6 中,使用 substring 方法可能会出现的问题是,如果你只需要使用很短的一段字符串,但是你实际上引用了整个字符串,这个很长的字符串无法被回收,造成了存储空间的浪费,甚至可能造成内存泄漏。这是一个已知...

    一文带你吃透Java中的String类.rar

    但是,如果String与其他对象组合形成引用链,可能会导致内存泄漏,这时需要注意及时解除引用,以便垃圾回收器能正确工作。 总之,Java中的String类是一个功能强大且基础的类,理解其特性和使用技巧对于提升编程效率...

    Java中String类(字符串操作)的10个常见问题和解决方法

    综上,Java中的String类提供了丰富的方法来处理字符串,但正确使用这些方法需要对Java内存模型、不可变对象和多线程安全等方面有深刻理解。这十个问题和解决方法,可以帮助开发者高效且正确地在Java中进行字符串操作...

    jdk6-8String类

    在1.6中,这个方法可能导致内存泄漏,因为它会将字符串添加到永久代(PermGen)中,这在处理大量动态字符串时可能会导致问题。 ### JDK 1.7中的String JDK 1.7对`String`类进行了一些性能优化,特别是在`...

    了解String.substring的原理

    总结来说,`String.substring`在不同的JDK版本中有不同的实现,从JDK 1.6到1.7的改进主要是为了防止因共享字符数组导致的内存泄漏。在编写涉及大量字符串操作的代码时,理解这些细节可以帮助我们更好地控制内存使用...

    Java宝典大全

    - **熟悉String的使用**: 如何正确使用`String`类的各种方法,如`equals()`、`indexOf()`、`substring()`等。 - **熟悉Java关键字**: 了解Java语言的关键字及其用途,如`final`、`static`、`abstract`等。 - **集合...

    Java常用类String的面试题汇总(java面试题)

    在Java编程语言中,String是一个非常重要的类,它被广泛用于表示和处理字符串数据。在面试中,关于String类的问题往往是必考题。以下是一些在面试中可能会遇到的问题,以及对应的解释和知识点汇总。 1. 在比较两个...

    Java 编程 :常见问题汇总

    4. **内存泄漏:** 在Java中,长时间持有不再使用的对象引用可能导致内存泄漏。应当及时释放不再使用的资源,比如关闭数据库连接、文件句柄等。 5. **性能优化:** 对于性能敏感的应用,应当关注算法的选择和数据...

    Java中的String为什么是不可变的共7页.pdf.z

    9. **内存管理**:由于每次修改都会创建新对象,过多的`String`操作可能导致内存泄漏。因此,在处理大量字符串操作时,需要注意性能优化。 10. **垃圾回收**:不可变性也有助于垃圾回收,因为当一个`String`对象...

    介绍 Java 的内存泄漏

    例如,在JDK6中,String的substring()方法在创建新字符串时,没有正确地解除对原字符串部分字符的引用,导致了内存泄漏。这个问题在JDK7中得到了修复。 防止内存泄漏的一些策略包括: 1. 适时清理集合类,避免使用...

    java面试考题

    面对内存泄漏问题,Java通过垃圾收集机制自动回收不再使用的对象,但过度复杂的引用结构可能导致内存无法释放,形成内存泄漏。 总之,Java面试中会涉及语言基础、面向对象特性、JVM、类加载、数据类型转换、排序...

    Java面试测试题目2018张大成总结

    ### Java面试测试题目知识点...- Java中使用静态变量来模拟全局变量的行为,避免全局变量可能导致的问题。 #### 57. 如何将String类型转化成Number类型 - 使用`Integer.parseInt()`、`Double.parseDouble()`等方法。

    十大常见Java String问题_动力节点Java学院整理

    本文总结了关于Java中String类最常见的十个问题,涉及字符串比较、敏感信息安全、switch语句中的使用、字符串与数字之间的转换、字符串拆分、字符串截取、可变字符串与不可变字符串的区别、字符串重复拼接、字符串...

    (超赞)JAVA精华之--深入JAVA API

    - **String类的常用成员方法** - 构造方法:如 `String(byte[] bytes, int offset, int length)` 用于从字节数组中构造字符串。 - `equalsIgnoreCase`: 忽略大小写的字符串比较。 - `indexOf`: 查找字符或子字符...

    Java SCJP中文学习指南

    String类在Java中是不可变的,它的常用方法如concat()、substring()、indexOf()等是SCJP考试的常见考点。同时,了解StringBuilder和StringBuffer线程安全的字符串操作也是必要的。 六、IO流与NIO 输入/输出流(IO流...

    Java面向对象面试题.pdf

    Java 中会存在内存泄漏吗,请简单描述。Java 中实现多态的机制是什么?垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收?等问题可以根据 Java 的语法和语义来回答...

    Java91个迷惑的问题

    4. **字符串操作**:Java中的`String`类有许多方法,如`concat()`, `substring()`, `trim()`等,理解它们的用法和行为差异是必要的。 5. **数组与集合**:Java中的数组和集合(如ArrayList, HashSet, HashMap等)的...

Global site tag (gtag.js) - Google Analytics