现在有代码 
String str = new String("abc");
String str1 = str;那我如果str1 = null;那么str的内存是不是不会得到回收?
怎么回收str的空间呢?
我有一个好几千万的循环,所以需要及时的回收内存。
实际问题就是读文件,文件几千万行,堆现在是256m,不希望继续扩了。
 while ((oneLine = reader.readLine()) != null)
这一行会报内存不足 java.lang.OutOfMemoryError: Java heap space
查看了readLine的源代码,里面会new一个string,类似上述的问题,所以发这个帖子求助大家。

解决方案 »

  1.   

    reader.readLine()没问题,你读出来的这一行行的内容是不是保存在某个list或其他什么对象里。
    应该是读出来的这些内容大小超出了堆的可用大小。如果每行数据比较大的话,几千万行的数据大小也不是小数目
      

  2.   

    出错就是报这行的呀
    我对oneLine =  reader.readLine()处理了下,没有保存
    但是有oneLine = null 提示回收呀
      

  3.   


    文件中每行并不长
    就是两个int 中间用空格分隔
      

  4.   

    oneLine=null,只是oneLine不引用其他对象,但只要该对象还被其他变量引用着,就不会被回收。
    如果文件不大的话,可能程序其他地方也占用了大量内存,这里只是加剧了内存占用,是导火索
      

  5.   


    reader.readLine()确实是导火线 文件很大 5000w条 但是每条记录就是两个int
      

  6.   

    帮我看看哪里内存使用出了问题 while ((oneLine = reader.readLine()) != null)
                {
                    
                 int idx = oneLine.indexOf('\t');
                 for(int i = 0; i < idx; i++)
                 {
                 strBuffer1.append(oneLine.charAt(i));
                 }
                 for(int i = idx + 1,len = oneLine.length(); i < len; i++)
                 {
                 strBuffer2.append(oneLine.charAt(i));
                 }
                
                    FollowerId = Integer.valueOf(strBuffer1.toString()).intValue();
                    FolloweeId = Integer.valueOf(strBuffer2.toString()).intValue();
                    strBuffer1.delete(0, strBuffer1.length());
                    strBuffer2.delete(0, strBuffer2.length());
                    oneLine = null;
                    //构建哈希表
                    ArrayList value = map.get(FollowerId);
                    if(value == null)
      {
    ArrayList arrayList = new ArrayList();
    arrayList.add(FolloweeId);
    map.put(FollowerId, arrayList);
    }
    }
      

  7.   


    补充下 文件格式是 两个int
    11111111  3456 
    我是要分隔 然后把int放入hash表
      

  8.   

    从你的程序来看,应该是map内存溢出了,文件几千万行,你转成String对象后,全部要存入map的List中,意味着整个文件实际上全部存入JVM内存了。不信的话,把这三句话注释掉,肯定不溢出了:
    ArrayList arrayList = new ArrayList();
    arrayList.add(FolloweeId);
    map.put(FollowerId, arrayList);
      

  9.   

    但是任务要求必须要建立hash表呀
    有什么办法吗
      

  10.   

    基本没招你这个是硬性内存要求。你文件总规模多大?另外你这么用StringBuffer意义不大,反而损耗性能,直接:
    String cuts[] = oneLine.split("\t");
    就得到两个字符串,然后:
    FollowerId = Integer.valueOf(cuts[0]);
    FolloweeId = Integer.valueOf(cuts[1]);
    然后还突然发现你最后那个构建哈希表应该有逻辑错误。
      

  11.   

    我内存跳到1g了 还是不行 因为有后序处理 所以这一步不能使用太多的内存
    文件总规模: 5000w个 int \t int
    String cuts[] = oneLine.split("\t"); 使用这个也会内存溢出,因为split底层使用的substring会引用分割前大的string的char数组,导致空间不足
    逻辑错误是指使用arraylist吗
    主要是要处理一对多的
      

  12.   

    这种局部资源释放都不会是问题,不过既然你是存入Map和List,其实可以不需要parseInt(),浪费速度和对象数量。逻辑错误是指如果value不是null,你就完全抛弃这个节点了。
    ArrayList value = map.get(FollowerId);
    if(value == null) {
                ArrayList arrayList = new ArrayList();
                arrayList.add(FolloweeId);
                map.put(FollowerId, arrayList);
    }
      

  13.   


    哦不好意思忘了一个else
                   else
    {
    value.add(FolloweeId);
    }另外 其实可以不需要parseInt(),浪费速度和对象数量
    这句不理解?
      

  14.   

    我put map.put(FollowerId  这里是安装integer大小算的吗 就是16b?
      

  15.   

    哦,说浪费速度和对像数量是一回事,不过你考虑了对象自身大小,确实Integer比String小,不过不止16b,应该是32b,另外还需要包括对象自身容量;毕竟它不是int这种基础类型。你的文件大小是多少?
      

  16.   

    把具体需求描述一下吧如果你的文件 很大  比如 10G 的文件 那么你如何修改 JVM内存都白费了考虑下 散列文件
      

  17.   


    这个规模我想很难完整装载进JVM了,尤其是你还想节省内存的话。List和Map自己的内存结构都是不小的开销,尤其Map有大量指针存储开销。你可以测试看看,把List和Map都去掉,哪怕把内存降低为128MB,也能正常跑完的。ArrayList value = map.get(FollowerId);
    /*if(value == null) {
      ArrayList arrayList = new ArrayList();
      arrayList.add(FolloweeId);
      map.put(FollowerId, arrayList);
    }*/要么就要用64位JVM,继续放大内存;要么就得换种算法了。
      

  18.   

    数据量太大,想完全放倒内存当中是个问题,建议考虑用别的方法。要么就优化部分算法以及继续扩大JVM的堆内存。
      

  19.   

    楼主,把这个数据直接存入数据库吧,看你用HashMap肯定是想做快速查找;但这个量太大,建议存入轻量级数据库(你这种KV型的,甚至可以用NoSQL),后续借助数据库来快速查找,效率也很高的。另一种方案是用MemCache/EHCache这种开源缓存组件,然后开启本地磁盘缓存能力,就可以超越内存容量限制。