0 0

String的substring方法. 难道是JAVA的bug?10

前几天写个小东西有个大问题。
使用java获取网页的源代码截东西。后来发现内存光涨不降。

发现String.substring中内容如果过大就有问题。
后来使用
String content = //获取网页内容 最好大一点
String temp = content.subString(0, 10);
String result = new String(temp);

return result;

如果直接返回temp。。。内存就有好瞧的。。大家可以试试下面的代码。基本上一分钟就over了。。最好用jconsole看效果。 呵呵。 如果是我其它的地方写错了。 请大家指正了。

验证程序 HttpClientUtil就是一取网页内容的。可以用别的替代。:
public class Test {

/**
* @param args
*/
public static void main(String[] args) {

String s1 = "http://finance.sina.com.cn/realstock/company/sz000831/nc.shtml";

List<String> s = new ArrayList<String>();
while(true){
String source = HttpClientUtil.getGetResponseWithHttpClient(s1, "gb2312");
String temp = source.substring(0, 10);
s.add(temp);
//s.add(new String(temp));
}

}

}


问题补充:
while(true){//这里的true是我特意加的。为的是延长时间来看到问题的出现。呵呵。 评论的那几位如果有空,请照着试一下就知道我说的情况了。 问题不在这个while的死循环。。。

问题补充:
我这个问题关心的是 使用subString后带来的内存问题。。。即便是使用 StringBuffer,在截取字符串的时候,还是要用 subString吧。
问题补充:
to: playfish
如果使用 s.add(new String(temp)); 就没任何问题。。。内存情况良好。

to: yourgame
呵呵,不清楚为什么你那里为什么会OK。
问题补充:
to sdh5724 :
我的代码是为了证明内存的只往上涨。。当然,你也可以说我的内存上涨是因为死循环造成的。 但使用 s.add(temp); 和 s.add(new String(temp)); 所造成的内存上升幅度则是有大区别。 如果你有空可以跑一下试试。

“以后能不能不用死循环来提问?

知道一秒要执行多少次么.........”

你跑一下就知道一秒执行多少次了。。。呵呵。 你的网络能有多快? 那是去取网页内容的。 我又不是多线程在跑。。。

另: 我也上传的内存使用情况的图片。 幅度不是一般的大。
问题补充:
谢谢 RednaxelaFX 的回答。应该是正解了。

同时也谢谢 playfish 。

不过,好像不能把分拆开吧。 我只好都给 RednaxelaFX  了
2009年3月25日 11:51
  • 大小: 79.9 KB
  • 大小: 87.4 KB

10个答案 按时间排序 按投票排序

0 0

采纳的答案

楼主的无限循环本来就是用来演示内存占用量的问题,是by-design的
用ArrayList来保存那些String显然不是个好做法,因为掩盖了楼主更关心的问题:substring()问题。

正好最近读帖的时候才有人提到过这个问题

James Watson 写道
Again I don't know C#, but one big gotcha with Strings in Java is that when you substring a large string, the underlying array is shared between the old String and the new String. So your original String object is released and GC'd but the underlying char array is not. If you have lots of big Strings, it looks like your Strings are not being GC'd because the array is the bulk of the memory used by the String. If C# Strings work the same way, I'd give you even odds that that was your problem.

楼主遇到的正好就是这个问题:使用substring()的时候,底下的字符数组的共享的,所以很可能会有String对象看来没有被释放到导致泄漏。嘛。

2009年3月25日 12:33
0 0


嗯,看来RednaxelaFX 的回答是正解

引用
使用substring()的时候,底下的字符数组的共享的,所以很可能会有String对象看来没有被释放到导致泄漏。


如果你的测试结果是这样的话,那说明你重新new String新建对象后原来的2个对象才会被GC回收释放掉.

2009年3月25日 13:05
0 0

以后能不能不用死循环来提问?

知道一秒要执行多少次么.........

2009年3月25日 12:54
0 0


lz说的应该没有错,但是这个应该不是bug

substring会创建一个新的string对象.内存自然就涨.你不断的循环执行,对象不断创建,而且你用list来保存,这些对象没有被销毁,越来越多,导致over.

如果想深入了解一下可以看下jdk的源代码,在你的JDK的安装目录下的src.zip里面解压出来看看里面的源代码.

2009年3月25日 12:26
0 0

if(source == null || source.length() <= 0){
   return;
}

这不会执行到的吧。

HttpClientUtil.getGetResponseWithHttpClient 不是类似Stream那样 read后,就变小一些的。

2009年3月25日 12:19
0 0

你把 HttpClientUtil 这个类给我 Q3990995

2009年3月25日 12:07
0 0

while(true){
String source = HttpClientUtil.getGetResponseWithHttpClient(s1, "gb2312");
if(source == null || source.length() <= 0){
   return;
}
String temp = source.substring(0, 10);
s.add(temp);
//s.add(new String(temp));

}

2009年3月25日 11:59
0 0

不过你这里很明显是个死循环

while(true){
String source = HttpClientUtil.getGetResponseWithHttpClient(s1, "gb2312");
String temp = source.substring(0, 10);
s.add(temp);
//s.add(new String(temp));
}

2009年3月25日 11:58
0 0

用StringBuffer 代替 效率高

2009年3月25日 11:57
0 0

while(true){
}

死循环吗?

2009年3月25日 11:51

相关推荐

Global site tag (gtag.js) - Google Analytics