Java 虚拟机内存溢出问题和解决方法

什么是内存溢出

  • 内存溢出是指应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用到的内存大于虚拟机能提供的最大内存。
  • Java的内存管理就是对象的分配和释放问题
  • 在Java中,内存的分配是由程序完成的,而内存的释放是由垃圾收集器(Garbage Collection,GC)完成的,程序员不需要通过调用GC函数来释放内存,因为不同的JVM实现者可能使用不同的算法管理GC,有的是内存使用到达一定程度时,GC才开始工作,也有定时执行的,有的是中断式执行GC。但GC只能回收无用并且不再被其它对象引用的那些对象所占用的空间。Java的内存垃圾回收机制是从程序的主要运行对象开始检查引用链,当遍历一遍后发现没有被引用的孤立对象就作为垃圾回收。

内存溢出的原因

  • 内存中加载的数据量过于庞大
  • 集合类中有对象的引用,使用完后未被清空
  • 代码中存在死循环或循环产生过多重复的对象
  • 启动参数内存值设定过小

解决办法

  • 修改JVM启动参数,直接增加内存。
    JVM默认可以使用的内存为64M,Tomcat默认可以使用的内存为128MB。这对于其他大型引用绝对是不够的
  • 检查错误日志,查看“OutOfMemory”错误前是否有其它异常或错误。
  • 对代码进行走查和分析,
    检查代码中是否有死循环或递归调用。
    检查是否有大循环重复产生新对象实体。
    检查对数据库查询中,是否有一次获得全部数据的查询,而没有使用分页。
    检查List、MAP等集合对象是否有使用完后,未清除的问题。List、MAP等集合对象会始终存有对对象的引用,使得这些对象不能被GC回收。
  • 尽早释放无用对象的引用。好的办法是使用临时变量的时候,让引用变量在退出活动域后,自动设置为 null ,暗示垃圾收集器来收集该对象,防止发生内存泄露。
    对于仍然有指针指向的实例, jvm 就不会回收该资源 , 因为垃圾回收会将值为 null 的对象作为垃圾,提高 GC 回收机制效率;
  • 我们的程序里不可避免大量使用字符串处理,避免使用 String ,应大量使用 StringBuffer ,每一个 String 对象都得独立占用内存一块区域;
    String str = “aaa”;
    String str2 = “bbb”;
    String str3 = str + str2;// 假如执行此次之后 str ,str2 以后再不被调用 , 那它就会被放在内存中等待 Java 的 gc 去回收 , 程序内过多的出现这样的情况就会报上面的那个错误。
  • 尽量少用静态变量,因为静态变量是全局的, GC 不会回收的;
  • 避免集中创建对象尤其是大对象, JVM 会突然需要大量内存,这时必然会触发 GC 优化系统内存环境;显示的声明数组空间,而且申请数量还极大。
    比如:
    有个excel文件上传的功能,excel内容有非常大,每次上传都导致jvm需要大量的内存。
  • 尽量运用对象池技术以提高系统性能;生命周期长的对象拥有生命周期短的对象时容易引发内存泄漏,例如大集合对象拥有大数据量的业务对象的时候,可以考虑分块进行处理,然后解决一块释放一块的策略。
  • 不要在经常调用的方法中创建对象,尤其是忌讳在循环中创建对象。可以适当的使用 hashtable , vector 创建一组对象容器,然后从容器中去取那些对象,而不用每次 new 之后又丢弃
  • 一般都是发生在开启大型文件或跟数据库一次拿了太多的数据,造成 Out Of Memory Error的状况,这时就大概要计算一下数据量的最大值是多少,并且设定所需最小及最大的内存空间值。
posted @ 2022-04-07 16:40  夏醉浅梦  阅读(351)  评论(0)    收藏  举报