运行环境jdk6,在一个解析报文的方法中使用到了String 类中的subString() 方法,很奇诡运行几天之后,内存就溢出了。从网上查了一下,发现 JDK6的String 类中的subString() 方法的确是有问题的。
jdk6 中方法的实现:
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类中存在这样三个属性
- value 字符数组,存储字符串实际的内容
- offset 该字符串在字符数组value中的起始位置
- count 字符串包含的字符的长度
验证subString() 内存泄露的程序
import java.util.Arrays;
public class TestString {
public String largeString = new String(new byte[100000]);
String getString() {
return this.largeString.substring(0,2);
}
public static void main(String[] args) {
java.util.ArrayList<String> list = new java.util.ArrayList<String>();
for (int i = 0; i < 1000000; i++) {
TestString gc = new TestString();
list.add(gc.getString());
for(String s:list){
System.out.print(s+"="+i);
}
}
System.out.println("==============");
}
}
运行结果:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.lang.StringCoding$StringDecoder.decode(StringCoding.java:133)
at java.lang.StringCoding.decode(StringCoding.java:173)
at java.lang.StringCoding.decode(StringCoding.java:185)
at java.lang.String.<init>(String.java:570)
at java.lang.String.<init>(String.java:593)
at boce.test.TestString.<init>(TestString.java:7)
at boce.test.TestString.main(TestString.java:21)
内存溢出了。
下面不使用 subString() 方法来截取字符串:
public class TestString {
public String largeString = new String(new byte[100000]);
String getString() {
byte[] b = Arrays.copyOfRange(largeString.getBytes(), 0, 2);
final String s = new String(b);
return s;
// String s = this.largeString.substring(0,2);
// return s;
//new String(this.largeString.substring(0,2));
}
public static void main(String[] args) {
java.util.ArrayList<String> list = new java.util.ArrayList<String>();
for (int i = 0; i < 10000000; i++) {
TestString gc = new TestString();
list.add(gc.getString());
System.out.print(list.get(i)+"="+i);
}
System.out.println("==============");
}
}
没有出现内存溢出的情况
相关推荐
在JDK的不同版本中,`String`类经历了一些优化和改进,尤其是在性能和内存管理方面。这里我们将对JDK 1.6、1.7和1.8中的`String`类进行对比研究,探讨其中的关键变化。 ### JDK 1.6中的String 在JDK 1.6中,`...
要解决 substring 方法引发的内存泄漏问题,我们可以使用 JDK 1.7 及以后的版本,因为在这些版本中,substring 方法已经被改进,避免了内存泄漏的问题。 如果我们无法升级到 JDK 1.7 及以后的版本,那么我们可以...
JDK 6的垃圾回收机制更加智能,提高了内存管理效率,降低了程序因内存泄漏导致的问题。 十四、性能优化 JDK 6在编译器、内存管理和类加载等方面进行了优化,提升了整体性能。 十五、JavaDoc JavaDoc工具在JDK 6中...
5. **字符串与字符流**:String类在JDK 6中有许多实用的方法,如concat()、substring()和indexOf()等。字符流(Reader和Writer)用于处理字符数据,理解字节流与字符流的区别及转换是必要的。 6. **输入/输出系统**...
在 JDK 6 中,使用 substring 方法可能会出现的问题是,如果你只需要使用很短的一段字符串,但是你实际上引用了整个字符串,这个很长的字符串无法被回收,造成了存储空间的浪费,甚至可能造成内存泄漏。这是一个已知...
总结来说,`String.substring`在不同的JDK版本中有不同的实现,从JDK 1.6到1.7的改进主要是为了防止因共享字符数组导致的内存泄漏。在编写涉及大量字符串操作的代码时,理解这些细节可以帮助我们更好地控制内存使用...
此外,`String`类还新增了`isEmpty()`方法,用于判断字符串是否为空,以及`substring()`方法的改进,允许负数索引,表示从字符串末尾开始计数。 在文件系统操作上,JDK7引入了`java.nio.file`包,提供了一组新的API...
3. **改进的字符串操作**:包括`switch`语句对字符串的支持,以及`String`类中新增的一些实用方法,如`join()`、`split()`和`substring()`的改进。 4. **文件系统API(NIO.2)**:Java 7引入了新的文件系统API,...
6. **改进的字符串操作**:`String`类在1.7版本中添加了多个实用方法,如`split()`的限制参数,`substring()`的改进,以及`contains()`, `startsWith()`, `endsWith()`的优化,提升了字符串处理的效率。 7. **...
例如,在JDK6中,String的substring()方法在创建新字符串时,没有正确地解除对原字符串部分字符的引用,导致了内存泄漏。这个问题在JDK7中得到了修复。 防止内存泄漏的一些策略包括: 1. 适时清理集合类,避免使用...
从JDK 7开始,substring()方法会创建一个新的char[]数组,这样可以避免潜在的内存泄漏。 7. String、StringBuilder与StringBuffer的对比 StringBuilder是可变的,适用于频繁修改字符串内容的场景。StringBuffer也是...
从Java 7开始,String类发生了变化,不再包含offset和count属性,这减少了每个String对象占用的内存,并解决了substring()方法可能导致的内存泄漏问题。此外,从Java 9开始,String对象的底层存储从char[]数组转变为...
在JDK 6中,substring操作是基于现有的字符数组,截取后不会创建新的数组。而在JDK 7中,substring方法返回的是一个新的字符数组,提高了效率,也便于垃圾回收器回收不再使用的旧字符串。 7. 如何将字符串转换成...
在JDK 6及以前版本中,substring()方法返回的字符串和原字符串共享一个char[]数组。从JDK 7开始,substring()方法会创建一个新的char[]数组,从而避免了在多线程环境中的安全问题。如果需要substring()返回一个全新...
以下代码创建大量substring,引发内存问题: ```java class Stringer { static final int MB = 1024 * 512; static String createLongString(int length) { StringBuilder sb = new StringBuilder(length); ...
1. String类:深入理解字符串的不可变性,字符串连接的性能优化,以及常用的方法如substring、indexOf、replace等。 2. Date和Calendar类:了解日期时间处理,如何进行日期的计算和格式化。 3. Reflection API:...
面对内存泄漏问题,Java通过垃圾收集机制自动回收不再使用的对象,但过度复杂的引用结构可能导致内存无法释放,形成内存泄漏。 总之,Java面试中会涉及语言基础、面向对象特性、JVM、类加载、数据类型转换、排序...
C++需手动管理内存,可能引发内存泄漏等问题。 #### Oracle JDK与OpenJDK - **Oracle JDK**:由Oracle公司维护的标准实现,提供官方支持和服务。 - **OpenJDK**:开源项目,任何人都可以参与贡献,兼容Oracle JDK但...