Java ArrayList 大批量添加String导致GC overhead limit exceeded问题

sfz634 2016-10-15 01:05:59
项目中遇到一个问题求教CSDN大牛们,在大批量创建Arraylist的过程中发现GC overhead limit exceeded的情况,具体情况简化如下。

项目中需要用Arraylist添加1000000次counter_temp字符串,counter_temp字符串需要100次累加得到。在运行到后期会出现GC overhead limit exceeded的情况,求大牛指点迷津,代码简化如下:

import java.util.ArrayList;

public class TestGC {

public static void main(String[] args) {
ArrayList list = new ArrayList();
String counter_temp=null;


for (int i = 0; i < 1000000; i++) {
long s = System.currentTimeMillis();
for (int j = 0; j < 100; j++){
if (counter_temp==null){
counter_temp="1";
}else{
counter_temp=counter_temp+"$1";
}
}
list.add(counter_temp);
long end = System.currentTimeMillis();
System.out.println(end-s);
}

}

}
...全文
960 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
ps45221 2016-11-02
  • 打赏
  • 举报
回复
引用 9 楼 Sun1956 的回复:
GC overhead limit exceeded 这个错误大概意思就是我花了太多的时间,,但是回收的垃圾太 少了, 可以通过加上-XX:-UseGCOverheadLimit参数禁止 你这里的问题在于,list加入太多的string,而String是放在常量池的, 虽然你add之后,把counter_temp=null, 但是此时list还是持有counter_temp那个字符串的引用的,所以不会释放这个字符串。
还有一点,忘记说了。 你这段代码,算一下所耗内存。这里假设一个字符要1字节,不算String对象本身占用的字节数, 你累加100次"$1",大约就是每个字符串就是200个长度,然后有100W个这样的Stirng加入list当中, 总共就是200 * 100W 个字节,大约190M,所以你的常量池要至少要有这么大。
ps45221 2016-11-02
  • 打赏
  • 举报
回复
GC overhead limit exceeded 这个错误大概意思就是我花了太多的时间,,但是回收的垃圾太 少了, 可以通过加上-XX:-UseGCOverheadLimit参数禁止 你这里的问题在于,list加入太多的string,而String是放在常量池的, 虽然你add之后,把counter_temp=null, 但是此时list还是持有counter_temp那个字符串的引用的,所以不会释放这个字符串。
bcsflilong 2016-11-02
  • 打赏
  • 举报
回复
是你累加的时候出现的问题吧 用 StringBuffer 吧 不用String
  • 打赏
  • 举报
回复
avails 2016-10-15
  • 打赏
  • 举报
回复
引用 5 楼 sfz634 的回复:
[quote=引用 4 楼 sfz634的回复:][quote=引用 3 楼 avails的回复:]这样做肯定能存溢出,这已经不是配置虚拟机能存能做的事情,换个思路。而且看你代码你那个list存入的字符越来越长,应该是写的不对。非得要这样做,那就分开,分几次处理,不然内存耗尽
谢谢层主,如果我把counter_temp替换成长度是500的固定字符串,是不会溢出的,说明不是字符串容量导致的,counter_temp离开作用域按道理应该已经释放内存了,ArrayList最后指向的也只是counter_temp最后的一次添加操作的内存区域,应该不会溢出才对啊……还是我的理解有什么不对的地方,求大牛指导[/quote] 不好意思贴代码的时候少了一个,add操作以后,中间漏了一个把counter_temp=Null,即便是添加了这一句,还是会溢出[/quote] 如果填入的字符串定长,那就看看-Xmx的值是多少,配置为512试试
sfz634 2016-10-15
  • 打赏
  • 举报
回复
引用 4 楼 sfz634的回复:
[quote=引用 3 楼 avails的回复:]这样做肯定能存溢出,这已经不是配置虚拟机能存能做的事情,换个思路。而且看你代码你那个list存入的字符越来越长,应该是写的不对。非得要这样做,那就分开,分几次处理,不然内存耗尽
谢谢层主,如果我把counter_temp替换成长度是500的固定字符串,是不会溢出的,说明不是字符串容量导致的,counter_temp离开作用域按道理应该已经释放内存了,ArrayList最后指向的也只是counter_temp最后的一次添加操作的内存区域,应该不会溢出才对啊……还是我的理解有什么不对的地方,求大牛指导[/quote] 不好意思贴代码的时候少了一个,add操作以后,中间漏了一个把counter_temp=Null,即便是添加了这一句,还是会溢出
sfz634 2016-10-15
  • 打赏
  • 举报
回复
引用 3 楼 avails的回复:
这样做肯定能存溢出,这已经不是配置虚拟机能存能做的事情,换个思路。而且看你代码你那个list存入的字符越来越长,应该是写的不对。非得要这样做,那就分开,分几次处理,不然内存耗尽
谢谢层主,如果我把counter_temp替换成长度是500的固定字符串,是不会溢出的,说明不是字符串容量导致的,counter_temp离开作用域按道理应该已经释放内存了,ArrayList最后指向的也只是counter_temp最后的一次添加操作的内存区域,应该不会溢出才对啊……还是我的理解有什么不对的地方,求大牛指导
avails 2016-10-15
  • 打赏
  • 举报
回复
这样做肯定能存溢出,这已经不是配置虚拟机能存能做的事情,换个思路。而且看你代码你那个list存入的字符越来越长,应该是写的不对。非得要这样做,那就分开,分几次处理,不然内存耗尽
piterlin 2016-10-15
  • 打赏
  • 举报
回复
内存溢出,解决思路有两方面:1,增大jvm的内存设置。2,重新设计,控制每次加载到内存的数据。 针对你举的例子,最好考虑思路2. 以下是思路1的参考: The following examples show how to set the maximum allowed size of allocated memory to 80 MB using various units: -Xmx83886080 -Xmx81920k -Xmx80m 参考:http://www.coderhelper.top/doc/technotes/tools/windows/java.html
bree06 2016-10-15
  • 打赏
  • 举报
回复
counter_temp字符串是固定的么?是怎样的字符串? 就算添加了counter_temp=Null也是不会释放的, 如果释放了那添加到list里的数据会怎么样?
sfz634 2016-10-15
  • 打赏
  • 举报
回复
自己顶一下,天降大牛!!!!!

58,454

社区成员

发帖
与我相关
我的任务
社区描述
Java Eclipse
社区管理员
  • Eclipse
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧