过期对象引用没有清理掉,会导致内存泄漏。对于没有用到的对象引用,可以置空,这是一种做法。而最好的做法是,把保存对象引用的变量清理掉,多用局部变量。

 
什么是内存泄漏?
在Java中,对象的内存空间回收是由Java垃圾回收器回收的。而Java垃圾回收器判定一个对象能否被回收的依据是,该对象是否可达。如果该对象可达,则垃圾回收器不会回收该对象的内存空间,反之,则回收。垃圾回收器判定一个对象是否可达,是根据该对象的引用链来决定的。
如果没有变量持有指向该对象的引用,那么,该对象就是不可达的。那么,垃圾回收器在下次回收的时候,就可以回收该对象。
如果,依然有变量持有指向该对象的引用,但是,我们找不到该变量,那么,就称为该对象泄漏了-----垃圾回收器不可以回收该对象,因为它依然可达;但是,我们不知道如何使用该对象,因为我们找不到指向该对象的引用。
当程序中,这种情况积聚很多的时候,就会导致内存泄漏。
 
场景一:
内存泄漏,丢失了指向该对象的引用
import java.util.Arrays;
import java.util.EmptyStackException; public class Stack {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack() {
elements = new Object[ DEFAULT_INITIAL_CAPACITY];
} public void push(Object e) {
ensureCapacity();
elements[size++] = e;
} public Object pop() {
if (size == 0)
throw new EmptyStackException();
return elements[-- size];
} /**
* Ensure space for at least one more element, roughly doubling the capacity each time the array
* needs to grow.
*/
private void ensureCapacity() {
if (elements.length == size)
elements = Arrays.copyOf(elements , 2 * size + 1);
}
}
--------------------------
问题出在这里:
  public Object pop() {
if ( size == 0)
throw new EmptyStackException();
return elements[-- size];
}
比方说,我入栈了10个元素,然后,我调用pop()方法,我调用6次pop()方法,这时,size是4,表明elemnts中还有4个元素。但是,实际上,elements还有另外6个存在,但是,这6个我们访问不到它们,但是它们是存在。这6个我们访问不到的元素,均持有指向相应对象的引用。
 
于是,就内存泄漏了----6个对象依然存在,垃圾回收器不会回收它们,因为有变量持有指向它们的引用;而我们访问不到这些变量。
 
将pop方法修改为:
  public Object pop() {
if (size == 0)
throw new EmptyStackException();
Object result = elements [--size ];
elements[size] = null;
return result ;
}
这样,出栈的元素,在elements中不再保留出栈元素中指向对应对象的引用。
 
 
场景二:
 
“内存泄漏的另一个常见来源是缓存。一旦你把对象引用放到缓存中,它就很容易被忘掉,从而使得它不再有用之后很长一段时间内依然留在缓存中。”
 
缓存的实现。
 
使用WeakHashMap。WeakHashMap适合的场景是,如果你要缓存的项(作为Map中的项),它的生命周期(也就是说,它什么时候被删除掉)是由该项的键(K)的外部引用决定的,而不是由该项的值(Value)决定的,那么,就可以使用WeakHashMap<K,V>来实现。
 
WeakHashMap<K,V>是这么个东西,它的K是一个对象,它有相应的内容。指向K的引用时一个弱引用,当K被置空的时候,或者当内存不够用的时候,垃圾回收器会回收K对象。当K对象被回收的时候,系统也会回收该K所在的项(K,V)。也就是说,Map中的项的存活是由K对象来决定的。
 
这里要考虑的问题是,K什么时候被置空。
WeakHashMap使用的一个例子:
实现需求的需求---保存每个存活的线程的信息,然后,可以在一个地方,根据线程来查询相应的信息。当线程死掉的时候,自动将其对应的信息清除掉。
 
这里面,线程什么时候死掉,也就是什么时候为空,这个是不确定的。这个适合使用WeakHashMap<K,V>数据结构来实现。
WeakHashMap<Thread,SomeMetaData>
当线程Thread死掉了,为空了,那么系统就会自动将相应的条目从WeakHashMap<Thread,SomeMetaData>中清除掉。
 
 
场景三:
 

Item 6 消除过期的对象引用的更多相关文章

  1. Effective Java 第三版——7. 消除过期的对象引用

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  2. Java 消除过期的对象引用

    内存泄漏的第一个常见来源是存在过期引用. import java.util.Arrays; import java.util.EmptyStackException; public class Sta ...

  3. 《Effective Java》 读书笔记(七)消除过期的对象引用

    大概看了一遍这个小节,其实这种感觉体验最多的应该是C/C++程序,有多杀少个new就得有多个delete. 一直以为Java就不会存在这个问题,看来是我太年轻. 感觉<Effective Jav ...

  4. Effective Java —— 消除过期的对象引用

    本文参考 本篇文章参考自<Effective Java>第三版第七条"Eliminate obsolete object references" Memory leak ...

  5. Effective Java (6) - 消除过期的对象引用

    一.引言 很多人可能在想这么一个问题:Java有垃圾回收机制,那么还存在内存泄露吗?答案是肯定的,所谓的垃圾回收GC会自动管理内存的回收,而不需要程序员每次都手动释放内存,但是如果存在大量的临时对象在 ...

  6. Effective Java 之-----消除过期的对象引用

    public class Stack { private Object[] elements; private int size = 0; private static final int DEFAU ...

  7. EffectiveJava(6)消除过期对象的引用

    消除过期对象的引用 过期引用 – 在操作集合类的时候,未清理过期的对象引用(即:过期引用),常会导致内存泄露.从而报outOfmemory错误. 1.过期对象导致内存泄漏. 2.一旦对象引用过期,清除 ...

  8. Effective Java 3

    <Effective Java>作者是美国的Joshua Bloch,连Gosling都说需要看的书,讨论的是更深层次的Java开发技术,适合于有一定Java基础的人看. 这是一本分享经验 ...

  9. Effective Java 创建和销毁对象

    <Effective Java>阅读笔记,用适合自己理解的方式提炼该书内容.<Effective Java>是一本很实用的书,阅读方法应该是快速的领会,总结,然后应用.而非,一 ...

随机推荐

  1. dataTables工作总结

    近期在工作中用到了dataTables,现在总结一下在工作中遇到的问题以及解决方法,如有不妥之处希望多多指教,定会改进. 首先这里用的是coloradmin框架,在vs环境下开发. 这里写一个容器用于 ...

  2. Python 再谈字符串

    字符串除了要用引号来创建之外,其他和元组一样,不能修改,如果要修改只能用切片或者拼接的方式. 其他的什么乱七八糟的运算符都一样 一些不同 capitalize()-将字符串的第一个字母大写 str1. ...

  3. ZooKeeper server &&client

    写了一个关于zookeepeer应用的简单demo 服务端定时的向zookeeper集群注册,客户端监听zookeeper服务节点变化,一旦变化,立刻响应,更新服务端列表 服务端代码: #includ ...

  4. dedecms添加新模型

    dedecms虽然预设了一些常见网页的功能模型,但是如果需要新的功能则需要自己创建,dedecms也提供了创建新模型的功能,如下: 1.打开后台首页=>核心=>内容模型管理 2.添加新模型 ...

  5. netem设置了网卡的流量控制,为啥发包的延迟就搞不定呢?

    为啥我用netem做了一个流量的控制 但是发送的时候,感觉真正发送数据的时候还是没有达到每一个数据包都是1s的延迟呀,这里的1s的延迟是啥意思啊? 这里的delay并不是说每个数据包都delay 5s ...

  6. [计算机网络-应用层] DNS:因特网的目录服务

    我们知道有两种方式可以识别主机:通过主机名或者IP地址.人们喜欢便于记忆的主机名标识,而路由器则喜欢定长的.有着层次结构的IP地址.为了折中这些不同的偏好,我们需要一种能进行主机名到IP地址转换的目录 ...

  7. WPF布局间的切换方法

    效果图,两种效果间的切换

  8. WPF绑定到父元素的属性的方法

    应用:绑定到父元素的属性上的方法,看图.

  9. 第三章 AOP

    什么是AOP AOP的编写方式 什么是AOP? 是一种面向切面的思想,关注的是切面中的相似功能,将这些功能抽离出来,提高代码的复用性 AOP术语 advice-通知:要执行的任务 Spring切面有5 ...

  10. 【题解】NOIP2015推销员

    ……普及组的题目都做不出来……(:´д`)ゞ……再这样下去要退役了啊…… 不过不管怎样感觉这题还是蛮好的,也要记录一下下~ 我们注意到数据的范围,n 是 1e5, 又有 1e5组询问,暴力大概是 \( ...