JVM内存溢出与内存泄露

1. 什么是内存溢出?

当前创建的对象的大小大于可用的内存容量大小,发生内存溢出。

在这里插入图片描述

2. 什么是内存泄露?

该回收的垃圾对象没有被回收,发生了内存泄露,垃圾对象越堆越多,
可用内存越来越少,若可用内存无法存放新的垃圾对象,就导致内存溢出。
内存泄露会导致内存溢出

在这里插入图片描述

3. 内存溢出的几种原因和解决办法

1.内存中加载的数据量过于庞大,如一次从数据库取出过多数据。

解决方法:检查对数据库查询中,是否有一次获得全部数据的查询;
	对于数据库查询尽量采用分页的方式查询。

2.集合类中有对对象的引用,使用完后未清空,使得JVM不能回收。

解决方法:检查List、MAP等集合对象是否有使用完后,未清除的问题。
	List、MAP等集合对象会始终存有对对象的引用,使得这些对象不能被GC回收。

3.代码中存在死循环循环产生过多重复的对象实体

解决方法:检查代码中是否有死循环或递归调用;
	检查是否有大循环重复产生新对象实体。

4.启动参数内存值设定的过小

解决方法:修改JVM启动参数(-Xms,-Xmx),直接增加内存。

4. 内存泄漏的几种原因

4.1 静态集合类引起内存泄漏

静态集合的生命周期和 JVM 一致,所以静态集合引用的对象不能被释放。

public classOOM{ 
	static List list =newArrayList();
	public void oomTests(){ 
		Object obj =new Object(); 
		list.add(obj);
	}
}

4.2 单例模式

和上面的例子原理类似,单例对象在初始化后会以静态变量的方式在 
JVM 的整个生命周期中存在。如果单例对象持有外部的引用,
那么这个外部对象将不能被 GC 回收,导致内存泄漏。

4.3 忘记关闭数据库连接、IO、Socket等资源

数据连接、IO、Socket等连接创建的连接不再使用时,需要调用 close 方法关闭连接,只有连接被关闭后,GC 才会回收对应的对象(Connection,Statement,ResultSet,Session)。
忘记关闭这些资源会导致持续占有内存,无法被 GC 回收。

try{ 
	Connection conn = null; 
	Class.forName("com.mysql.jdbc.Driver"); 
	conn = DriverManager.getConnection("url","",""); 
	Statement stmt = conn.createStatement(); 
	ResultSet rs = stmt.executeQuery("....");
}catch(Exception e){
 
}finally{
  //不关闭连接
}}

4.4 变量不合理的作用域

一个变量的定义作用域大于其使用范围,很可能存在内存泄漏;或不再使用对象没有及时将对象设置为 null,很可能导致内存泄漏的发生。

public class Simple{ 
	Object object;
	public void method1(){ 
		object =newObject();
		//...其他代码
		//由于作用域原因,method1执行完成之后,
		//object 对象所分配的内存不会马上释放
		object = null;
 }}

4.5 ThreadLocal 造成的内存泄漏

ThreadLocal 可以实现变量的线程隔离,但若使用不当,就可能会引入内存泄漏问题。
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值