第六条 消除过期的引用

原创 2016年06月01日 15:57:09

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结束的生命周期里取消注册。


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



相关文章推荐

第六条:消除过期的对象引用

这段程序有一个“内存泄漏”问题,如果一个栈先是增长,然后再收缩,那么,从栈中弹出来的对象不会被当做垃圾回收,即使使用栈的程序不再引用这些对象,它们也不会被回收。这是因为,栈内部维护这对这些对象的过期使...

软硬件调试九法:第六条规则 保持审计跟踪

1、把你的操作、操作顺序和结果全部记录下来   要记录所做的事、做事的顺序、以及发生的结果,每次做完都要全部记录。就像调试硬件一样,必须指导每个步骤以及执行结果,才能确定下一步关注的重点。 ...

第五条-消除过期的对象引用

package EffectiveJava; import java.util.Calendar; import java.util.Date; public class _2_4 { ...

高效Java06:消除过期的对象引用

类自己管理内存一般而言,只要是类自己管理内存,我们就应该警惕内存泄漏问题。比如下面的例子:public class Stack { private Object[] elements; ...

006-消除过期的对象引用

006---消除过期的对象引用 ———————————————————— 看下面的代码: 这段代码会造成内存泄漏!先是栈不断增长,然后再是栈不断收缩,那么从栈中弹出的对象将不会被当做垃圾回...

Effective Java 第6条:消除过期的对象引用

当你从手工管理内存的语言(比如C或C++)转换到具有垃圾回收功能的语言的时候,程序员的工作会变得更加容易,因为当你用完了对象之后,它们会被自动回收。当你第一次经历对象回收功能的时候,会觉得这简直有点不...

(6):消除过期的对象引用

java有自己的垃圾回收功能,这大大减少了程序员的负担。但对于有些被引用的对象,即使我们之后再也不使用它,它也不会被回收,这就是所谓的内存泄漏。 下面是一个简单的栈实现例子: public class...

Effective Java学习笔记四(消除过期的对象引用)

public class Stack { private Object[] elements; private int size = 0; private static fin...
  • ayw255
  • ayw255
  • 2016年12月16日 10:33
  • 113

06-消除过期的对象引用

java 虽然有垃圾回收机制,但是对于被引用的对象,就算我们已经不再使用,它的回收机制可能也不会进行回收,称之为内存泄漏。书中有这样一个例子,先看代码:public class Stack { ...

Java性能优化(5):消除过期的对象引用

当你从一种手工管理内存的语言(比如C/C++)转换到一种具有垃圾回收功能的语言的时候,作为一个苦逼的程序猿,工作这时候变得更加容易。因为当你用完了对象后,它们会自动被回收(现实中的对象可不能这样啊(ฅ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:第六条 消除过期的引用
举报原因:
原因补充:

(最多只允许输入30个字)