内存泄漏的第一个常见来源是存在过期引用。

 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];
} private void ensureCapacity() {
if (elements.length == size) {
elements = Arrays.copyOf(elements, 2 * size + 1);
}
} public void push(Object e) {
ensureCapacity();
elements[size++] = e;
} public Object pop() {
if (size == 0) {
throw new EmptyStackException();
} return elements[--size];
} }

  如果一个栈先是增长,然后再收缩,从栈中弹出来的对象不会被当作垃圾回收,即使使用栈的程序不再引用这些对象,它们也不会被回收。因为栈内部维护着对这些对象的过期引用(obsolete reference)。过期引用指永远也不会再被解除的引用。在本例中,在elements数组的“活动部分(active portion)”之外的任何引用都是过期的。活动部分指elements中下标小于size的那些元素。

  如果一个对象引用被无意识地保留了,垃圾回收机制不仅不会回收这个对象,而且不会回收被这个对象所引用的所有其他对象。解决方法:一旦对象引用已经过期,只需清空这些引用即可。在本例中,只要一个元素被弹出栈,指向它的引用就过期了。修改如下:

 public Object pop() {
if (size == 0) {
throw new EmptyStackException();
} Object result = elements[--size];
elements[size] = null; // 清空引用 return result;
}

  清空过期引用的另一个好处是,如果它们以后又被错误地解除引用,程序会立即抛出NullPointerException异常,而不是悄悄地错误运行下去。尽快地检测出程序中的错误总是有益的。消除过期引用最好的方法是让包含该引用的变量结束其生命周期。如果在最紧凑的作用域范围内定义每一个变量(见第45条),这种情形会自然而然地发生。

  只要类是自己管理内存,程序员就应该警惕内存泄漏问题。一旦元素被释放掉,该元素中包含的任何对象引用都应该被清空。

  内存泄漏的第二个常见来源是缓存。

  把对象引用放到缓存中,它就很容易被遗忘掉,从而使得它不再有用之后很长一段时间内仍然留在缓存中。用WeakHashMap代表缓存时,当缓存中的项过期之后,它们会被自动地删除。只有当缓存项的生命周期是由该键的外部引用而不是由值决定时,WeakHashMap才起作用。

  随着时间的推移,缓存项会变得越来越没有价值,缓存应该时不时地清除掉没用的项。可以由一个后台线程(可能是Timer或者ScheduledThreadPoolExecutor)来完成,或者在给缓存添加新条目时进行清理。LinkedHashMap类可以通过它的removeEldestEntry方法来实现后者。对于更加复杂的缓存,必须直接使用java.lang.ref。

  内存泄漏的第三个常见来源是监听器和其他回调。

  如果客户端在自己实现的API中注册回调,却没有显式地取消注册,那么除非自己采取某些动作,否则它们就会积聚。确保回调立即被当作垃圾回收的最佳方法是只保存它们的弱引用(weak reference),例如,只将它们保存为WeakHashMap中的键。

  往往只有通过仔细检查代码,或者借助于Heap剖析工具(Heap Profiler)才能发现内存泄露问题。

  参考资料

  《Effective Java 中文版 第2版》 第6条:消除过期的对象引用 P21-23

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

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

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

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

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

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

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

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

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

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

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

  6. Item 6 消除过期的对象引用

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

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

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

  8. Java中对象、对象引用、堆、栈、值传递以及引用传递的详解

    Java中对象.对象引用.堆.栈.值传递以及引用传递的详解 1.对象和对象引用的差别: (1).对象: 万物皆对象.对象是类的实例. 在Java中new是用来在堆上创建对象用的. 一个对象能够被多个引 ...

  9. java cache过期策略两种实现,一个基于list轮询一个基于timer定时

    最近项目要引入缓存机制,但是不想引入分布式的缓存框架,所以自己就写了一个轻量级的缓存实现,有两个版本,一个是通过timer实现其超时过期处理,另外一个是通过list轮询.       首先要了解下ja ...

随机推荐

  1. 理解DeepBox算法

    理解DeepBox算法 基本情况 论文发表在ICCV2015,作者是Berkeley的博士生Weicheng Kuo: @inproceedings{KuoICCV15DeepBox, Author ...

  2. Html列表分页算法

    public class PageHelper { /// <summary> /// 标签 /// </summary> public string Tag { get; s ...

  3. 一个良好划分Activity创建步骤的BaseActivity

    一个Activity的创建过程其实包含几个不同的步骤,基本上都是在onCreate函数中完成的,这些步骤主要有: 设置页面的布局文件 初始化页面包含的控件 设置页面控件的点击响应事件 处理页面的业务逻 ...

  4. Storm——Android SQLite数据库管理类库

    Storm是一个Android SQLite数据库管理类库,可以通过注解创建表和迁移数据库.它不是ORM框架.   特性: 1.通过@Annotations创建表: 2.通过@Annotations迁 ...

  5. python全栈开发day51-jquery插件、@media媒体查询、移动端单位、Bootstrap框架

    一.昨日内容回顾 技术行业 (1)ajax技术 XMLHttpRequest() <1>创建XMLHttpRequest()对象 <2>检测状态(通过readyState的改变 ...

  6. Python_list部分功能介绍

    x.append():在列表尾部添加一个元素 x.clear():把列表清空 x.count():判断某个元素出现的次数 x.extend():合并两个列表,或者一个元组 x.index():获取元素 ...

  7. net core体系-API-1Ocelot-(1)概要

    从这篇开始探讨Ocelot,Ocelot是一个.NET API网关,仅适用于.NET Core,用于.NET面向微服务/服务的架构中.当客户端(web站点.ios. app 等)访问web api时, ...

  8. 使用Phar来打包发布PHP程序

    简单来说,Phar就是把Java界的jar概念移植到了PHP界. Phar可以将一组PHP文件进行打包,还可以创建默认执行的stub(或者叫做 bootstrap loader),Phar可以选择是否 ...

  9. AtCoder Grand Contest 11~17 做题小记

    原文链接https://www.cnblogs.com/zhouzhendong/p/AtCoder-Grand-Contest-from-11-to-20.html UPD(2018-11-16): ...

  10. eclipse中设置自动生成的author,date等注释

    转自:http://blog.csdn.net/zhouhong1026/article/details/38396311 转自:http://hi.baidu.com/qianjian21/blog ...