内存泄漏
内存泄漏是指不再被程序使用的对象或者变量还在内存中占存储空间
内存泄漏主要有两种情况:一是在堆中申请的空间没有被释放;二是对象已经不再使用,但仍然在内存中保留着,垃圾回收器则无法保证不再使用的对象会被释放.因此java语言中的内存泄漏主要指第二种情况(因为GC会解决第一种情况)
例如:
Vector v=new Vector(10);
for(int i=0;i<10;i++){
Object o =new Object();
v.add(o);
}
当循环退出后,o的作用域将会结束,但是由于v在使用这些对象,因此垃圾回收器无法将其回收,此时就造成了内存泄漏.只有将这些对象从Vector删除后才能释放创建的对象
引起内存泄漏的原因?
①静态集合类,如HashMap和Vector.如果这些容器为静态的,由于它们的生命周期和程序一致,那么容器中的对象在程序结束之前不能被释放,从而造成内存泄漏
②各种连接.如数据库连接和IO连接等.在对数据库进行操作的过程中,首先需要建立和数据库的连接,当不再使用时需要调用close方法来释放和数据库的连接,只有连接被关闭后,垃圾回收器才会回收相应的对象
③监听器.通常一个应用会用到多个监听器,在释放对象的同时如果没有删除监听器,也有可能导致内存泄漏
④变量不合理的作用域.如果一个变量定义的作用范围大于其使用范围,很可能会造成内存泄漏,另一方面如果没有及时地把对象设置为null,很有可能导致内存泄漏的发生
如:
class Server{
private String msg;
public void receiveMsg(){
readFromNet();//从网络中收到数据保存到msg中
saveDB(); //把msg保存到数据库中
}
}
将msg的信息保存到数据库后,此时msg已经没用了,由于msg的生命周期和对象的声明周期相同,此时msg还不能被回收,因此造成了内存泄漏.
解决方法
①将msg定义为局部变量
②使用完msg后就把msg设置为null
⑤单例模式可能会造成内存泄漏.单例模式的实现方法有很多种,下例中所使用的单例模式就可能会造成内存泄漏
class BigClass{
}
class Singleton{
private BigClass bc;
private static Singleton instance=new Singleton(new BigClass());
private Singleton(BigClass bc){
this.bc=bc;
}
public Singleton getInstance(){
return instance;
}
}
Singleton存在一个对对象BigClass的引用,由于单例对象以静态变量的方式存储,因此它在jvm的整个生命周期中都存在,同时它有一个对对象BigClass的引用,这样会导致BigClass类的对象不能被回收
内存溢出
程序需要的内存超过了系统所能分配的范围.内存泄漏时内存溢出的诱因,但不是唯一因素.将抛出OutOfMemoryError异常
内存溢出的原因
①内存泄漏的原因
②堆内存溢出(OutOfMemoryError存放的对象过多)
③方法区溢出(OutOfMemoryError加载的类过多,或者使用反射、cglib等这种动态代理生成类的技术,就可能导致该区发生内存溢出)
④线程栈溢出(StackOverflowError线程栈时线程独有的一块内存结构,所以线程栈发生问题必定是某个线程运行时产生的错误。 一般线程栈溢出是由于递归太深或方法调用层级过多导致的。)
内存泄漏的解决办法
1.修改JVM启动参数,直接增加内存。(-Xms,-Xms参数一定不要忘记加)
2.检查错误日志,查看“OutOfMemory”错误前是否有其他异常或错误。
3.对代码进行走查和分析,找出可能发生内存溢出的位置。