内存泄漏概念

1、何为内存泄漏

申请了内存用完了不释放

当一个对象是否被使用,当现在不需要。还一直存在。

即:对象不会再被程序用到了。但是GC又不能回收他们的情况,才叫内存泄漏

如果对象的生命周期过长也会出现内存泄漏(OOM)

占着茅坑不拉shi

2、内存溢出

申请内存时,没有足够的内存可以使用

当内存线漏增多,最终会导出内存溢出

3、内存泄漏的8种情况

3.1、静态集合类

public class demo1 {
    static List list=new ArrayList();

    public void oomTests(){
        Object obj=new Object();
        list.add(obj);
    }
}

3.2、单例模式

单例模式生命周期和JVM一样长,如果持用外包对象的引用,那么这个外部对象也不会被回收,那么就会造成内存泄露

3.3、内部类持有外部类

内部类持有外部类,如果一个外部类的实例对象的方法返回一个内部类的实例对象,

这个内部类对象被长期引用了,即使那个外部类实例对象不再被使用,单由于内部类持有

外部类的实例对象,这个外部类对象不会被垃圾回收,这也会造成内存泄漏

3.4、各种连接,如数据库连接,网络连接和IO连接等

建立连接后需要释放连接

3.5、变量不合理的作用域

一个变量的定义的作用范围大于其使用范围,很有可能会造成内存泄漏。另外一方面,如果没有及时地把对象设置为null,很有可能导致内存线漏

public class demo2 {
    private String msg;
    
    public void receiveMsg(){
        readFromNet();//从网络中接受数据保存到msg中
        saveDB();//把msg保存到数据库中
    }
}

3.6、改变哈希值

改变哈希值,当一个对象被存储进HashSet集合中以后,就不能修改这个对象中那些参与计算哈希值的字段了,否则,对象修改后的哈希值与最初存储进行HashSet集合中时的哈希值就不同了

这种情况下,即使在contains方法使用该对象的当前引用作为的参数去HashSet中集合中检索对象,也将返回找不到对象的结果。这也会导致无法从HashSet集合中单独删除当前对象,造成内存泄露

public class ChangeHashCode1 {
    public static void main(String[] args) {
        HashSet<Point> hs = new HashSet<Point>();
        Point cc = new Point();
        cc.setX(10);//hashCode = 41
        hs.add(cc);

        cc.setX(20);//hashCode = 51  此行为导致了内存的泄漏

        System.out.println("hs.remove = " + hs.remove(cc));//false
        hs.add(cc);
        System.out.println("hs.size = " + hs.size());//size = 2

        System.out.println(hs);
    }

}

class Point {
    int x;

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + x;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null) return false;
        if (getClass() != obj.getClass()) return false;
        Point other = (Point) obj;
        if (x != other.x) return false;
        return true;
    }

    @Override
    public String toString() {
        return "Point{" +
                "x=" + x +
                '}';
    }
}

3.7、缓存泄露

public class MapTest {
    static Map wMap = new WeakHashMap();
    static Map map = new HashMap();

    public static void main(String[] args) {
        init();
        testWeakHashMap();
        testHashMap();
    }

    public static void init() {
        String ref1 = new String("obejct1");
        String ref2 = new String("obejct2");
        String ref3 = new String("obejct3");
        String ref4 = new String("obejct4");
        wMap.put(ref1, "cacheObject1");
        wMap.put(ref2, "cacheObject2");
        map.put(ref3, "cacheObject3");
        map.put(ref4, "cacheObject4");
        System.out.println("String引用ref1,ref2,ref3,ref4 消失");

    }

    public static void testWeakHashMap() {

        System.out.println("WeakHashMap GC之前");
        for (Object o : wMap.entrySet()) {
            System.out.println(o);
        }
        try {
            System.gc();
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("WeakHashMap GC之后");
        for (Object o : wMap.entrySet()) {
            System.out.println(o);
        }
    }

    public static void testHashMap() {
        System.out.println("HashMap GC之前");
        for (Object o : map.entrySet()) {
            System.out.println(o);
        }
        try {
            System.gc();
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("HashMap GC之后");
        for (Object o : map.entrySet()) {
            System.out.println(o);
        }
    }

}

3.8、监听器和回调

如果客户端在你实现API中注册回调,却没有显示取消,那么就会积聚。

需要确保回调立即被当做垃圾回收的最佳方法是只保存它的弱引用,例如将他们保存成为

WeakHashMap中的键

总结:

集合,数组,如果进行增删改。操作不正确。是的引用集合的指针操作不当,会存在内存泄露

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

追逐路上的小人物

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值