46、JVM实战:内存溢出

29–内存溢出

1、什么是内存溢出

就是应用系统所需的内存大于虚拟机的堆内存

2、内存溢出的原因

1、 内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
2、 集合类中对对象的引用,使用完后未清空,使得JVM不能回收;
3、 代码中存在死循环或循环产生过多重复的对象实体;

3、解决办法


3.1、修改JVM启动参数,直接增加内存。

3.2、检查错误日志,查看"OutOfMemory"错误前是否有其它异常或错误。

3.3、对代码进行走查和分析,

1、 检查代码中是否有死循环或递归调用;
2、 检查是否有大循环重复产生新对象实体;
3、 检查对数据库查询中,是否有一次获得全部数据的查询,而没有使用分页;
4、 检查List、MAP等集合对象是否有使用完后,未清除的问题;

1、 List、MAP等集合对象会始终存有对对象的引用,使得这些对象不能被GC回收;

3.4、尽早释放无用对象的引用。

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

3.5、我们的程序里不可避免大量使用字符串处理,避免使用 String ,因为每一个 String 对象都得独立占用内存一块区域,所有应使用 StringBuffer

String str = "aaa";   
  
String str2 = "bbb";   
  
String str3 = str + str2;// 假如执行此次之后 str ,str2 以后再不被调用 , 那它就会被放在内存中等待 Java 的 gc 去回收 , 程序内过多的出现这样的情况就会报上面的那个错误 .

3.6、尽量少用静态变量,因为静态变量是全局的, GC 不会回收的

3.7、避免集合中创建对象尤其是大对象。

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

举例

1、 显示的声明数组空间,而且申请数量还极大;
2、 比如:有个excel文件上传的功能,excel内容有非常大,每次上传都导致jvm需要大量的内存;

3.8、尽量运用对象池技术以提高系统性能

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

3.9、不要在经常调用的方法中创建对象,尤其是忌讳在循环中创建对象。

可以适当的使用hashtable, vector创建一组对象容器,然后从容器中去取那些对象,而不用每次 new 之后又丢弃