Java内存溢出与内存泄漏

内存溢出:内存溢出就是指在指定大小的内存空间,写入了超出大小的数据(越界).或者没有足够的内存,供程序分配。


内存泄漏:程序在运行过程中动态申请的内存空间不再使用后没有及时释放,从而很可能导致应用程序内存无线增长。更广义的内存泄露包括未对系统的资源的及时释放,比如句柄等。


结果: 1.内存溢出:程序将停止
      2.内存泄漏:程序不会停止但是效率会降低,内存泄漏过多也可能造成内存溢出。


Java 内存泄漏:
发生情况及解决方法:
  1.静态集合类,如HashMap 和Vector
            静态集合类的生命周期和程序一致,一次集合对象不用时应及时将其设为Null。
  2.各种连接,如数据库连接,网络连接,I/O连接。
            连接不用时应将其Close,否则GC不会回收相应的对象。
  3.监听器。
            在释放对象时,必须删除相应的监听器。
  4.变量的不合理作用于。若对象仅在局部使用,却被声明在更大的作用范围当中,就可能造成内存泄漏,或者没有及时的将对象设为null,也会造成内存泄漏。
            对象声明,应该和其使用范围一致,并且使用结束后及时设为Null。


避免方法:
         1) 尽早释放无用对象的引用。


          好的办法是使用临时变量的时候,让引用变量在退出活动域后自动设置为null,暗示垃圾收集器来收集该对象,防止发生内存泄露。


          2) 程序进行字符串处理时,尽量避免使用String,而应使用StringBuffer。


          因为每一个String对象都会独立占用内存一块区域,如:


         3) 尽量少用静态变量。


         因为静态变量是全局的,GC不会回收。


         4) 避免集中创建对象尤其是大对象,如果可以的话尽量使用流操作。


          JVM会突然需要大量内存,这时会触发GC优化系统内存环境; 


         5) 尽量运用对象池技术以提高系统性能。


          生命周期长的对象拥有生命周期短的对象时容易引发内存泄漏,例如大集合对象拥有大数据量的业务对象的时候,可以考虑分块进行处理,然后解决一块释放一块的策略。


         6) 不要在经常调用的方法中创建对象,尤其是忌讳在循环中创建对象。
 
          可以适当的使用hashtable,vector 创建一组对象容器,然后从容器中去取那些对象,而不用每次new之后又丢弃。


         7) 优化配置




Java 内存溢出:
     
区域  1.堆内存溢出  java.lang.OutOfMemoryError:Java heap space
      2.栈溢出
      3.方法区(包括常量池)溢出  java.lang.OutOfMemoryError: PermGen space 加载了过多的类,jar等
      4.直接内存溢出
 
情况:1、在程序中存在死循环,或者循环过多,而产生了过多重复的对象的实例;
     2、存在对象的引用,使用完后没有清除,导致JAVA虚拟机不能回收;如集合的使用。
     3、一次操作时,在内存中加载了大量的数据;(算法空间复杂度过高) 
     4.使用的第三方软件中的BUG; 
     5.启动参数内存值设定的过小;
原则上来说,在JAVA中,由于它的自动垃圾回收机制,出现内存溢出的可能性并不是很大。




排查:
    1.检查代码中是否有死循环或递归调用。 
    2.检查是否有大循环重复产生新对象实体。 
    3.检查对数据库查询中,是否有一次获得全部数据的查询。一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查询就有可能引起内存溢出。因此对于数据库查询尽量采用分页的方式查询。 
    4.检查List、MAP等集合对象是否有使用完后,未清除的问题。List、MAP等集合对象会始终存有对对象的引用,使得这些对象不能被GC回收。 




解决:  1.从代码层面进行优化完善,尽量避免该情况发生;
          一:
            1.对那些静态(static)的对象要特别留神,特别是类型为Map,List,Set的,静态的变量会一直驻存在内存中,生命周期比较长,不会被垃圾器回收。
            2.对于代码,要审查是否生成了大量的冗余的对象,还有一些逻辑业务处理的类,
          算法是否过于复杂,调整算法,对于代码认真审查,再仔细重构一遍代码,能提高代码质量,提高程序运行稳定性。
           
          3.Java中的内存溢出大都是因为栈中的变量太多了。其实内存有的是。建议不用的尽量设成null以便回收,多用局部变量,少用成员变量。
          4.在我的程序中对静态变量的优化后,使程序占用内存量至少提升了5k-10k。所以也不容忽视。


          二:
            还有就是String类相关的东西:
          1.字符串累加的时候一定要用StringBuffer的append方法,不要使用+操作符连接两个字符串。差别很大。而且在循环或某些重复执行的动作中不要去创建String对象,因为String对象是要用StringBuffer对象来处理的,一个String对象应该是产生了 3个对象(大概是这样:))。
          2.字符串length()方法来取得字符串长度的时候不要把length放到循环中,可以在循环外面对其取值。(包括vector的size方法)。特别是循环次数多的时候,尽量把length放到循环外面。


             3 写代码的时候处理内存溢出   
                   try{   
                      //do   sth    
                   }catch   (outofmemoryerror   e){//可以用一个共通函数来执行.   
                    system.out.print   (“no   memory!   ”);   
                    system.gc();   
                     //do   sth   again   
                  ....   
                   }          
             4.对于频繁申请内存和释放内存的操作,还是自己控制一下比较好,但是System.gc()的方法不一定适用,最好使用finallize强制执行或者写自己的finallize方法。 Java 中并不保证每次调用该方法就一定能够启动垃圾收集,它只不过会向JVM发出这样一个申请,到底是否真正执行垃圾收集,一切都是个未知数。


       2.调整优化JVM,服务器配置(调整参数): 


         1) 设置-Xms、-Xmx相等;


         2) 设置NewSize、MaxNewSize相等;


         3) 设置Heap size, PermGen space(永久代空间)
 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值