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

 
什么是内存泄漏?
在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. Java学习个人备忘录之数组

    数组 概念:同一种类型数据的集合,其实数组就是一个容器. 数组的好处:可以自动给数组中的元素从0开始编号,方便操作这些元素. 格式1:元素类型[] 数组名 = new 元素类型[元素个数]; 格式2: ...

  2. java多线程三之线程协作与通信实例

    多线程的难点主要就是多线程通信协作这一块了,前面笔记二中提到了常见的同步方法,这里主要是进行实例学习了,今天总结了一下3个实例: 1.银行存款与提款多线程实现,使用Lock锁和条件Condition. ...

  3. ifream爱恨情缘

    开幕场景 iframe.html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "h ...

  4. iOS- UIButton/UIImageView/UISlider/UISwitch操作

    如果看不到图片 可以尝试更换浏览器(推荐Safari ) 一.控件的属性 1.CGRect frame 1> 表示控件的位置和尺寸(以父控件的左上角为坐标原点(0, 0)) 2> 修改这个 ...

  5. 我们在删除SQL Sever某个数据库表中数据的时候,希望ID重新从1开始,而不是紧跟着最后一个ID开始需要的命令

    一.如果数据重要,请先备份数据 二.删除表中数据 SQL: Delete From ('表名')  如:Delete From abcd 三.执行新语句 SQL: dbcc checkident('表 ...

  6. [剑指Offer] 55.链表中环的入口结点

    题目描述 一个链表中包含环,请找出该链表的环的入口结点. [思路]根据set集合的不重复,遍历链表时遇到的第一个重复结点就是环的入口结点. /* struct ListNode { int val; ...

  7. DBGrid相关技术整理

    DBGrid相关技术整理: 注:对于DBGrid相关属性.方法的学习融入到技术整理过程中 一,多选 设置属性: Options->dgMultiSelect = True; ->dgRow ...

  8. 第71天:jQuery基本选择器(二)

    jQuery选择器 一.内容过滤选择器 选择器 描 述 返 回 示 例 :contains(text) 匹配含有文本内容text的元素 集合元素 $(“p:contains(今天)”) :empty ...

  9. 在a标签的href用户#name 的可以实现页面 上下跳转

  10. HDU 4869 Turn the pokers(思维+逆元)

    考试的时候没有做出来... 想到了答案一定是一段连续的区间,一直在纠结BFS判断最后的可行1数. 原来直接模拟一遍就可以算出来最后的端点... 剩下的就是组合数取模了,用逆元就行了... # incl ...