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

 
什么是内存泄漏?
在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. IE中的activex控件

    1.tree控件 DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML><HE ...

  2. hadoop下安装mysql

    http://www.cnblogs.com/zhuyp1015/p/3561470.html       第一步:先把这个文件放入到linux环境下桌面. 接着编写脚本:sudo apt-get u ...

  3. ZOJ 1539 L-Lot

    https://vjudge.net/contest/67836#problem/L Out of N soldiers, standing in one line, it is required t ...

  4. 加密和数字签名工具GPG

    转载: 源文件位置:http://blog.chinaunix.net/uid-9525959-id-2001824.html GPG [功能]  GPG是加密和数字签名的免费工具,大多用于加密信息的 ...

  5. 读取游标 BEGIN END

    USE db_2008 --引入数据库 DECLARE ReadCursor CURSOR --声明一个游标 FOR SELECT * FROM Student OPEN ReadCursor --打 ...

  6. centos7 nginx端口转发出现502的其中一种原因

    在排查了一系列可能的原因后仍无法解决,经资料查阅可能是SELinux造成,SELinux很强大但若配置不当也会造成很多组件无法正常使用,这里直接将其关闭: //打开配置文件 vi /etc/selin ...

  7. MATLAB中imfilter函数

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

  8. HUAS 1480 虫洞(最短路)

    把每个点拆成两个点,分别表示黑洞和白洞,然后按题意模拟加边跑最短路即可. # include <cstdio> # include <cstring> # include &l ...

  9. [HNOI2010]合唱队 区间DP

    ---题面--- 题解: 偶然翻到这道题,,,就写了. 观察到一个数被插在哪里只受前一个数的影响,如果明确了前一个数是哪个,那么我们就可以确定大小关系,就可以知道当前这个数插在哪里,而上一个插入的数就 ...

  10. [SDOI2017]新生舞会 0/1分数规划

    ---题面--- 题解: 0/1分数规划,,,但是竟然有诡异的精度问题???因为这个被卡了好久 中途还写过一次KM,,,结果陷入死循环,,,我大概是写了一个假KM,,,于是放弃KM,回来调费用流 这个 ...