java有内存溢出吗?如果有是什么情况?


内存溢出是指应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用到的内存大于虚拟机能提供的最大内存。  
所以我们应该明确:存在内存溢出的因不一定导致内存溢出的果。。。  
  
  
1。JAVA操作文本文件为什么超过3万行就内存益处啊?  
  
PrintWriter  out  =  new  PrintWriter(new  BufferedWriter(new  FileWriter(fileName)));    
          //PrintWriter  out  =  new  PrintWriter(fileName);    
          //FileOutputStream  out  =  new  FileOutputStream(fileName);    
      
            while  (rs.next())  {    
              for  (int  j  =  1;  j  <=  totalColumn;  j++)  {    
                  out.write(rs.getObject(j).toString());    
                  out.write("\t");    
              }    
                out.write("\n");    
                out.flush();    
      
                      }    
  }    
  我在代码中  写了  out.flush()用来刷新该流的缓冲;  可是当我的记录数超过3W时就报了内存益处的问题了,难道JAVA不能边读边写吗?还是out这个对象随着指向的fileName文件的边大占用内存也大了吗??到底怎么来实现用JAVA写更多的数据而不内存益处呢  
  
  
答案是:就在while(rs.next())  当rs.next()时内存不断增大,而不是写流的问题,JAVA的ResultSet真是麻烦,而且ResultSet还不能clone();  所以记得在做项目的时候,经常要设置:jdbc.setMaxRows(100*10000);  //设置能容纳100万行记录-----这个就是防止内存泄露的哈------------------- 内存中加载的数据量过于庞大,如一次从数据库取出过多数据;   
jdbc.setQueryTimeout(60*30); //设置超时时间是30分钟  
  
  
2。java中的内存泄露的情况:长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不能被回收,这就是java中内存泄露的发生场景,通俗地说,就是程序员可能创建了一个对象,以后一直不再使用这个对象,这个对象却一直被引用,即这个对象无用但是却无法被垃圾回收器回收的,这就是java中可能出现内存泄露的情况,例如,缓存系统,我们加载了一个对象放在缓存中(例如放在一个全局map对象中),然后一直不再使用它,这个对象一直被缓存引用,但却不再被使用。  
 public class Stack { //长生命周期  
    private Object[] elements=new Object[10]; //当数组容器中没有东西时是无用的,但是无法回收~~elements是短生命周期  
    private int size = 0;  
    public void push(Object e){  
    ensureCapacity();  
    elements[size++] = e;  
    }  
    public Object pop(){  
    if( size == 0)  
throw new EmptyStackException();  
//这里还是引用了,只是指针变位置变化而已,他确实返回了那个对象,但是他却没有断开那个对象的引用,也就是说有两个地方会持有这个对象的引用,调用pop的地方,和elements中  
    return elements[--size];   
    }  
    private void ensureCapacity(){  
    if(elements.length == size){  
    Object[] oldElements = elements;  
    elements = new Object[2 * elements.length+1];  
    System.arraycopy(oldElements,0, elements, 0, size);  
    }  
    }  
    }  
    上面的原理应该很简单,假如堆栈加了10个元素,然后全部弹出来,虽然堆栈是空的,没有我们要的东西,但是这是个对象是无法回收的,这个才符合了内存泄露的两个条件(必要条件):无用,无法回收。  
   例子1  
    public class Bad{  
    public static Stack s=Stack();  
    static{  
    s.push(new Object());  
    s.pop(); //这里有一个对象发生内存泄露  
    s.push(new Object()); //上面的对象可以被回收了,等于是自愈了,因为引用被覆盖了  
    }  
    }  
    因为是static,就一直存在到程序退出,但是我们也可以看到它有自愈功能,就是说如果你的Stack最多有100个对象,那么最多也就只有100个对象无法被回收其实这个应该很容易理解,Stack内部持有100个引用,最坏的情况就是他们都是无用的,因为我们一旦放新的进取,以前的引用自然消失!  
  
内存泄露的另外一种情况:当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了,否则,对象修改后的哈希值与最初存储进HashSet集合中时的哈希值就不同了,在这种情况下,即使在contains方法使用该对象的当前引用作为的参数去HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从HashSet集合中单独删除当前对象,造成内存泄露。  
  
  
这是属于: 集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;  
  
3。代码中存在死循环或循环产生过多重复的对象实体;  
  
4。启动参数内存值设定的过小;
参考资料:java陷阱-------内存溢出

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐