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

 
什么是内存泄漏?
在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. 20145214 《Java程序设计》第1周学习总结

    20145214 <Java程序设计>第1周学习总结 教材学习内容总结 第一章 了解了Java的诞生和版本演进的历史,目前的最新版本是Java SE8. java的三大平台分别是Java ...

  2. 转 Js 跨域CORS报错 Response for preflight has invalid HTTP status code 405

    转自:http://www.cnblogs.com/SilenceTom/p/6697484.html 调用接口遇到Response for preflight has invalid HTTP st ...

  3. C#部分语法总结

    1. Frst和FirstOrDefault 1. Fist 如果查询的数据不存在, 则抛System.InvalidOperationException异常 2. FirstOrdefault 如果 ...

  4. 【重读MSDN之ADO.NET】ADO.NET连接

    连接到ADO.NET中的数据源 在 ADO.NET 中,通过在连接字符串中提供必要的身份验证信息,使用 Connection 对象连接到特定的数据源.使用的 Connection 对象取决于数据源的类 ...

  5. 通过设置窗体的AcceptButton属性,可以设置窗体的“接受”按钮,若此设计,则用户每次按下Enter键都相当于单击该按钮

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  6. ipython matplotlib

    matplotlib实际上是一套面向对象的绘图库,它所绘制的图表中的每个绘图元素,例如线条Line2D.文字Text.刻度等在内存中都有一个对象与之对应.为了方便快速绘图matplotlib通过pyp ...

  7. 判断集合不为空Java

    list.size>0判断集合size是否大于0 list.isEmpty()判断集合是否为空,返回布尔值

  8. MATLAB中imfilter函数

    功能:对任意类型数组或多维图像进行滤波. 用法:B = imfilter(A,H) B = imfilter(A,H,option1,option2,...) 或写作g = imfilter(f, w ...

  9. BZOJ 1816 扑克牌(二分)

    由于答案具有单调性,考虑二分答案并验证. 如果能凑齐x堆,因为每个joke在一个牌堆里最多只能用一次,则至多只能用min(x,m)个joke. 对于每个牌,如果这个牌的总数小于x,用joke补齐剩下的 ...

  10. 【bzoj4922】[Lydsy六月月赛]Karp-de-Chant Number 贪心+背包dp

    题目描述 给出 $n$ 个括号序列,从中选出任意个并将它们按照任意顺序连接起来,求以这种方式得到匹配括号序列的最大长度. 输入 第一行包含一个正整数n(1<=n<=300),表示括号序列的 ...