关闭

第六条 消除过期的引用

标签: java广播监听
180人阅读 评论(0) 收藏 举报
分类:

java 中有自动垃圾回收机制,如果以为不用自己手动处理,jvm可以全局处理,那就有点错了

例如

 public class Stack {

private Object[] elements;
private int size = 0;
private static final int DEFAULT = 16;

public Stack(){
elements = new Object[DEFAULT];
}

public void push(Object o){
ensure();
elements[size++] = o;
}

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


private void ensure(){
if(elements.length == size){
elements = Arrays.copyOf(elements, size *2 +1);
}
}
}

joshua大神的例子

这段代码看起来没问题,但有个小问题:内存泄漏。随着数组笔挺变大,程序性能会下降,应为 数组 elements 不停增大,调用 pop()功能,数据仍然存在数组中,极端情况,数组会造成内存泄漏 oom。 一个类似的例子时集合,我们用到集合后,有些小伙伴会在不用时置空,以为完事,其实置空前应该先 clean()一下,清除集合里面的元素,然后吧集合对象置空。


同理,上述数组中,可以修改  pop()方法,在弹出数组对象时,把数组里面的引用置空

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

清除过期引用的另一个好处是一旦被错误引用,程序会立刻抛出异常,而不是悄悄的继续错误的运行下去。

effective java 作者 joshua大神明确说:清空对象引用应该是一种例外,而不是一种规范行为。

是不是觉得前后矛盾? 这么说主要是因为 对于每一个程序对象,一旦不用就清空,很容易把代码弄混乱,消除过期引用的最好方法时控制其生命周期来结束引用,而不是到处置空。一般而言,只要是类自己管理内存,我们就该警惕内存泄漏了,就像是上述代码一样。

另一种是缓存。把对象引用放入缓存,很容易就被遗忘。对于这种,常见的解决方案是弱引用。缓存中的内容过期后,自动被删除。或者采用类似 LinkedHashMap 的容器,在增加新条目的同时会自动清理以前的条目,对于更复杂的封装好的缓存工具,可以使用 java.lang.ref。


第三种常见的是监听器和其他回调。如果只注册回调,没有对应的取消注册,那么就会越聚越多,造成内存泄漏。Android中常见的就是广播注册,没有在activity结束的生命周期里取消注册。


内存泄漏是一个大的模块,只有在平常中积累,才能慢慢提高。



0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:6883次
    • 积分:494
    • 等级:
    • 排名:千里之外
    • 原创:45篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章分类