第六条 消除过期的引用

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


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



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

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

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

在像JAVA这种
  • u014723123
  • u014723123
  • 2014年06月22日 14:28
  • 744

第六条:消除过期的引用变量

为什么要消除过期的引用变量: 因为JAVA是用垃圾收集机制回收内存的。 当只有在变量未被任何类使用的情况下才会被回收。但是当我们编写程序的时候,往往会无意识的保持对象。 导致垃圾回收机制无法回收...
  • chen19960724
  • chen19960724
  • 2016年08月15日 17:19
  • 235

消除过期的对象引用

 Java的垃圾回收确实帮助我们解决了不少内存管理的问题,但是,这并不意味着我们就可以完全依赖Java的垃圾回收。我们还是在编写程序的时候需要考虑内存管理的问题,例如:class Stack{publ...
  • netHibernate
  • netHibernate
  • 2006年10月21日 11:41
  • 2025

第6条 创建和销毁对象——消除过期的对象引用

1、如果一个栈先是增长,然后再收缩,那么从栈中弹出来的对象将不会被当作垃圾回收,即使使用栈的程序不再引用这些对象,它们也不会被回收。这是因为,栈内部维护着对这些对象的过期引用。所谓的过期引用是指永远不...
  • Xi__Yuan
  • Xi__Yuan
  • 2016年05月03日 15:01
  • 479

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

都说java有垃圾自动回收机制,但是在开发过程中仍然有可能导致内存泄漏问题。下面有几种造成内存泄漏的来源。一、过期引用看下面的代码,这个简单的栈就存在“过期引用”的问题。当栈进行增长再收缩时,publ...
  • lsluffy
  • lsluffy
  • 2017年11月02日 18:02
  • 34

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

第六条:消除过期的对象引用 1,  如果一个栈先是增长,然后再收缩,那么在栈中弹出来的对象将不会被当做垃圾回收,即使使用栈的程序不再引用这些对象,它们也不会被回收,因为,在栈的内部保存了对象的过期引用...
  • sdywcd
  • sdywcd
  • 2009年07月29日 23:19
  • 594

创建和销毁对象 第六条:消除过期的对象引用

考虑下面实现栈的例子:/** * $desc * Created by zfy on 2016/10/28. */public class Stack { private Object[...
  • sinat_33661267
  • sinat_33661267
  • 2016年10月28日 15:25
  • 346

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

当你从一种手工管理内存的语言(比如C/C++)转换到一种具有垃圾回收功能的语言的时候,作为一个苦逼的程序猿,工作这时候变得更加容易。因为当你用完了对象后,它们会自动被回收(现实中的对象可不能这样啊(ฅ...
  • pangjiuzala
  • pangjiuzala
  • 2015年08月20日 15:52
  • 1666

JAVA消除过期的对象引用

  下面的例子存在内容泄漏(或者说无意识的对象保持,unintentional object retention)。//Can u spot the "memory leak"?public clas...
  • fightplane
  • fightplane
  • 2005年01月10日 17:11
  • 2547
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:第六条 消除过期的引用
举报原因:
原因补充:

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