内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;
内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。
memory leak会最终会导致out of memory!
内存泄漏
长生命周期的对象引用短声明周期的对象,导致短生命周期的对象在生命周期已结束后还无法回收对象内存 ,造成内存泄漏
场景
- 1、静态集合引用对象
public class dome1 {
static Set<Object> s = new HashSet(10);
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
Object o = new Object();
s.add(o);
//对象赋值位空值,理应被垃圾回收器回收,但是被集合引用,
// 但是GC-Roots 到对象之间存在引用链(可到达),
//所以不会被回收内存
o = null;
}
s.forEach(System.out::println);
}
}
- 2、集合里面的对象属性被修改,在调用remove()方法时不起作用,造成对象删除不掉,造成内存泄漏
HashSet<Person> set = new HashSet<>();
Person tom = new Person(1L, "Tom", 12);
System.out.println(tom.hashCode());//2613467
set.add(tom);
tom.setAge(13);//修改对象的属性后对象的hashCode发生变化
System.out.println(tom.hashCode());//2613468
System.out.println(set.remove(tom));//false remove不成功,造成内存泄漏
set.forEach(System.out::println);
System.out.println(set.add(tom));// true 添加成功,判断是否相等时验证hashCode
set.forEach(System.out::println);
-
3、监听器未删除
-
4、各种连接为关闭
数据库链接、网络链接、IO链接必须显式的调用close关闭链接,否则不会被GC回收
-
5、内部类和外部模块的引用
-
6、单例模式引用其他对象
单例模式为静态资源,整个JVM生命周期都有效,如果单例对象持有对外部对象的引用,那么这个外部对象不会被GC回收,导致内存泄漏
if (true){
Person tom = new Person(1L, "Tom", 12);
singleton.getInstance().setPerson(tom);
}
System.out.println(singleton.getInstance().getPerson());
对象tom已经结束生命周期,但是被单例对象引用,不会被GC回收
二、内存溢出
在Java堆中不断的创建对象造成
大量的内存泄漏