欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java内存泄漏

程序员文章站 2022-07-10 15:03:16
...

Java内存泄漏

  • 什么是内存泄漏?

        内存泄漏指的是存在“不再使用但持有引用”的对象,它们无法被GC回收,占用了内存的现象。轻微的内存泄漏不容易被察觉,严重的内存泄漏容易导致OOM(out of memory)。

 

  • 哪些操作可能导致内存泄漏?
  1. 使用静态集合或数组而没有及时使用清除指向对象的引用导致;
  2. 使用 Set 集合保存对象,当修改对象属性后,无法通过该对象删除导致;
  3. 没有及时释放资源连接(IO连接,数据库连接,Socket网络连接等)导致,应在 finally 块中释放资源;
  4. 外部类持有内部类的引用没有及时清除;
  5. 模块之间方法调用,在参数中传递了对象引用,如果在被调用的模块方法中又将该引用赋值给了另一个引用,那么对于该传递的对象(堆上的对象)而言,需要同时清除多个引用才能被回收;
  6. 单例对象中如果持有其他对象的引用,那么该引用无法被清除;
  7. 使用 GUI API 编程时,使用到的各种监听器,是比较容易被忽略释放的;Java Web 编程中,监听器同样会被使用,但总体来说,数量有限。

Case 1

Static List<Object> list = new ArrayList<>(100);
for (int i = 1; i < 100; i ++) {
    Object o = new Object();
    list.add(o);
    o = null;// 只清除了创建时指向该对象的引用,而集合中仍然持有该对象引用
}

 

Case 2

// 以下这段代码基于 Person 对象重写了 hashCode() 方法
// 因为 HashSet 集合的删除是基于 Map 的,Set 集合中的对象在 Map 中
// 作为 key,而 Map(数组 + 链表)中 key 所在的数组的索引是根据 key 
// 的 hashCode() 计算的,当改变了 Set 中的对象,再用改变后的对象去
// 删除,自然是删除不掉的。

public static void main(String[] args) {
        Set<Person> set = new HashSet<Person>();
        Person p1 = new Person("唐僧","pwd1",25);
        Person p2 = new Person("孙悟空","pwd2",26);
        Person p3 = new Person("猪八戒","pwd3",27);
        set.add(p1);
        set.add(p2);
        set.add(p3);
        System.out.println("总共有:"+set.size()+" 个元素!"); //结果:总共有:3 个元素!
        p3.setAge(2); //修改p3的年龄,此时p3元素对应的hashcode值发生改变
        set.remove(p3); //此时remove不掉,造成内存泄漏
        set.add(p3); //重新添加,居然添加成功
        System.out.println("总共有:"+set.size()+" 个元素!"); //结果:总共有:4 个元素!
}

 

其余略。

 

参考: http://blog.csdn.net/wtt945482445/article/details/52483944

 

 

 

相关标签: Java 内存泄漏