码迷,mamicode.com
首页 > 其他好文 > 详细

常见内存泄漏的来源

时间:2021-02-22 12:42:58      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:过滤   默认   exception   方法   清理   入栈   --   管理   概率   

来源一:过期引用

public class Stack {
	// 底层使用的是数组 没毛病
    private Object[] elements;
    // size作为指针 没毛病
    private int size = 0;
    // 默认容量 没毛病
    private static final int DEFAULT_INITIAL_CAPACITY = 16;
	
    public Stack() {
        elements = new Object[DEFAULT_INITIAL_CAPACITY];
    }
    
	// 扩容机制
    private void ensureCapacity() {
        if (elements.length == size) {
            elements = Arrays.copyOf(elements, 2 * size + 1);
        }
    }
	
	// 入栈
    public void push(Object e) {
        ensureCapacity();
        elements[size++] = e;
    }
    
	// 出栈 (注意这个方法!!!)
    public Object pop() {
        if (size == 0) {
        throw new EmptyStackException();
    }
        return elements[--size];
    }

}

这里内存泄漏的风险点是从栈中弹出的对象不会被垃圾回收器回收,是因为栈虽然不再使用这些对象,但内部却维护着他们的过期引用。所谓过期引用,是指永远也不会再被解除的引用,一个解决方案是,对该位置置NULL

public Object pop() {
    if (size == 0) {
    throw new EmptyStackException();
}
    Object rs = elements[--size];
    elements[size] = null
    return rs
}

那么是否来说,针对这些集合,我们都采用此方案呢,当然不合适,如果这样,不仅仅会使代码变脏,也不一定适用于所有场景。
一般来说,只要是类自己管理内存,就应该警惕内存泄漏问题。

扩展:

静态集合类,如HashMap、LinkedList等等。如果这些容器为静态的,那么它们的生命周期与程序一致,则容器中的对象在程序结束之前将不能被释放,从而造成内存泄漏。简单而言,长生命周期的对象持有短生命周期对象的引用,尽管短生命周期的对象不再使用,但是因为长生命周期对象持有它的引用而导致不能被回收。

解决办法是最好不使用静态的集合类,如果使用的话,在不需要时要将其赋值为null。如果是不使用的key,调用remove即可,map和list的remove方法不存在栈的这个问题,直接清除了对象引用,那么不存在强引用,该值自然也会被回收。

无需过分在意此类场景,低概率事件,遇见时考虑可能时这种情况。

来源二:缓存

缓存当没有对象引用时,往往也会放在内存中,等待过期策略去清理,书中提到的weakHashMap,在对其调用get,put等方法时,就会过滤一遍是否存在弱引用,存在则移除,会出现两个问题,

1.遍历会得到不同结果

  • 调用两次size()方法返回不同的值;
  • 两次调用isEmpty()方法,第一次返回false,第二次返回true;
  • 两次调用containsKey()方法,第一次返回true,第二次返回false,尽管两次使用的是同一个key;
  • 两次调用get()方法,第一次返回一个value,第二次返回null,尽管两次使用的是同一个对象。

2.如果没有引用就清楚,而缓存通常是在某个时间段被高频使用,而不是不间断都有引用。(待实践确认)

所以我觉得用weakHashMap代替不太好,至于3则适用weakHashMap

监听器和其他回调

如果你实现了一个API,客户端在这个KPI中注册回调,但是没有显式的取消注册,那么在你没有对其作特殊处理的情况下,他们就会不断堆积,从而导致泄漏。解决方法和上面的例子一样,将它们保存为WeakHashMap的键即可。

weakhashmap介绍

java的几种引用

常见内存泄漏的来源

标签:过滤   默认   exception   方法   清理   入栈   --   管理   概率   

原文地址:https://www.cnblogs.com/kunkka-0717/p/14426510.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!