`
bingooh
  • 浏览: 53275 次
  • 性别: Icon_minigender_1
  • 来自: 佛山
社区版块
存档分类
最新评论

2.6 移除过时的对象引用

 
阅读更多

如下代码(以下代码来自Effective Java一书):

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);
	}
}

 

使用以上Stack类,如果循环放入100个不同的对象,接着循环弹出此100个对象,其私有属性elements数组仍然“引用”被弹出的100个对象,从而导致JVM不能回收此100对象所占用的内存,即内存泄露

 

注:

内存泄露:指对象占用的内存不能回收,甚至不断增大。导致JVM因内存不足频繁启动GC,进而降低程序运行性能。

内存溢出:指程序需要使用的内存,超出JVM所能使用的最大内存。内存溢出后JVM会终止并退出

 

为了解决此问题,可以进行如下修改,在弹出对象后,把elements对其的引用指向null。进而被弹出的对象可以被回收:

	public Object pop() {
		if (size == 0)
			throw new EmptyStackException();
		Object result = elements[--size];
		elements[size] = null; // Eliminate obsolete reference
		return result;
	}

 

大多数情况下都不应该把变量显式的设置为null,以移除过时的引用。而是应该利用变量的作用域,在变量超出作用域范围后,利用GC自动移除所引用的对象(即JVM的GC机制)。变量的作用域应尽可能的小。

 

只有在编码者需要自行管理对象,即只有编码者知道创建的对象是否还需要使用的情况下,才需要显式的设置相关引用为null,以便GC能回收此对象。如上例对象被从elements移除后(这里移除只是修改了size变量的值),只有编程者知道Stack对象是否还需要使用被移除的对象,如果不需要使用,Stack对象不应该继续引用被移除的对象,所以需要显式的设置引用为null

 

以下情况需要考虑移除过时的引用:

1.类需要自行管理内存,如上Stack类自行管理elements数组。当对象被从elements移除后(这里移除只是修改了size变量的值),应该显式的设置对应的引用为null,以便GC。否则因为Stack仍然引用了被移除的对象,JVM不会对其进行GC

 

2.使用Cache,需要自行管理缓存的对象的移除

 

3.添加listener或callback对象,需要自行管理添加的listener或callback的移除

 

可以使用WeakHashMap管理添加的缓存对象或listener对象。WeakHashMap对添加的key对象使用“弱引用”,当除了WeakHashMap外,没有任何其他对象引用添加的key对象时,此key对象可以被GC。在GC时会从WeakHashMap里移除

 

需要注意的是WeakHashMap对添加的value对象仍然使用强引用。如果添加的value对象引用了key对象(或者其他对象应用了key对象),那么此key对象不会被GC。在添加value对象时,可以使用WeakReference进行封装。这样,如果仅有WeakHashMap对象引用value对象,那么value对象会被GC,进而key对象也被GC

 

 

 

 

 

 

 

分享到:
评论

相关推荐

    重构_改善既有代码的设计

     8.3 ChangeValuetoReference(将值对象改为引用对象)179  8.4 ChangeReferencetoValue(将引用对象改为值对象)183  8.5 ReplaceArraywithObject(以对象取代数组)186  8.6 DuplicateObservedData(复制“被...

    重构:改善既有代码的设计(中文版).

    8.3 ChangeValuetoReference(将值对象改为引用对象)179 8.4 ChangeReferencetoValue(将引用对象改为值对象)183 8.5 ReplaceArraywithObject(以对象取代数组)186 8.6 DuplicateObservedData(复制“被监视数据...

    重构_改善既有代码的设计.pdf

    8.3 ChangeValuetoReference(将值对象改为引用对象)179 8.4 ChangeReferencetoValue(将引用对象改为值对象)183 8.5 ReplaceArraywithObject(以对象取代数组)186 8.6 DuplicateObservedData(复制“被监视数据...

    重构:改善既有代码的设计(中文高清版)

    8.3 ChangeValuetoReference(将值对象改为引用对象)179 8.4 ChangeReferencetoValue(将引用对象改为值对象)183 8.5 ReplaceArraywithObject(以对象取代数组)186 8.6 DuplicateObservedData(复制“被监视数据...

    重构-改善既有代码的设计

     8.3 ChangeValuetoReference(将值对象改为引用对象)179  8.4 ChangeReferencetoValue(将引用对象改为值对象)183  8.5 ReplaceArraywithObject(以对象取代数组)186  8.6 DuplicateObservedData(复制“被...

    重构-改善既有代码的设计 中文版.pdf

    8.3 Change Value to Reference(将实值对象改为引用对象) 8.4 Change Reference to Value(将引用对象改为实值对象) 8.5 Replace Array with Object(以对象取代数组) 8.6 Duplicate Observed Data(复制「被...

    《重构改善既有代码的设计(2010年版)》(Martin Fowler[美] 著,熊节 译)

    8.3 ChangeValuetoReference(将值对象改为引用对象)179 8.4 ChangeReferencetoValue(将引用对象改为值对象)183 8.5 ReplaceArraywithObject(以对象取代数组)186 8.6 DuplicateObservedData(复制“被监视数据...

    重构-改善既有代码的设计 中文版

    8.3 Change Value to Reference(将实值对象改为引用对象) 8.4 Change Reference to Value(将引用对象改为实值对象) 8.5 Replace Array with Object(以对象取代数组) 8.6 Duplicate Observed Data(复制「被...

    重建——改善既有代码的设计

    8.4 ChangeReferencetoValue(将引用对象改为值对象)183 8.5 ReplaceArraywithObject(以对象取代数组)186 8.6 DuplicateObservedData(复制“被监视数据”)189 8.7 ...

    重构:改善既有代码的设计.[美]Martin Fowler.epub【文字版手机格式】

    8.3 Change Value to Reference(将值对象改为引用对象) 8.4 Change Reference to Value(将引用对象改为值对象) 8.5 Replace Array with Object(以对象取代数组) 8.6 Duplicate Observed Data(复制“被监视数据”...

    中文版Excel.2007高级VBA编程宝典.part1

     7.9.3 对象的引用  7.10 属性和方法  7.10.1 对象的属性  7.10.2 对象的方法  7.11 Comment对象示例  7.11.1 查看有关Comment对象的帮助  7.11.2 Comment对象的属性  7.11.3 Comment对象的方法  7.11.4 ...

    Java核心技术II(第8版)

    7.13.6 使用本地剪贴板来传递对象引用 7.14 拖放操作 7.14.1 Swing对数据传递的支持 7.14.2 拖曳源 7.14.3 放置目标 7.15 平台集成 7.15.1 闪屏 7.15.2 启动桌面应用程序 7.15.3 系统托盘 第八章 JavaBean构件 8.1 ...

    Jqury基础教程

    2.6 DOM遍历方法 2.6.1 为特定单元格添加样式 2.6.2 连缀 2.7 访问DOM元素 2.8 小结 第3章 事件 3.1 在页面加载后执行任务 3.1.1 代码执行的时机选择 3.1.2 基于一个页面执行多个脚本 3.1.3 缩短代码的简写...

    Java Web编程宝典-十年典藏版.pdf.part2(共2个)

    2.3.3 引用标签库指令taglib的使用 2.4 使用JSP脚本 2.4.1 在JSP中应用代码片段 2.4.2 使用JSP表达式 2.4.3 声明标识的使用 2.5 注释的魅力 2.5.1 基本的HTML注释 2.5.2 JSP隐藏注释 2.5.3 代码片段中的注释 2.6 ...

    jquery基础教程高清版PDF.part5.rar

     2.6 DOM遍历方法   2.7 访问DOM元素   2.8 小结  第3章 事件——扣动扳机   3.1 在页面加载后执行任务   3.1.1 代码执行的时机选择   3.1.2 基于一个页面执行多个脚本   3.1.3 缩短代码的...

    flex3的cookbook书籍完整版dpf(包含目录)

    2.6节. 设置控件的labelFunction 2.7节. 提供菜单数据 2.8. 动态填充菜单 2.9节. 为菜单类控件创建事件处理函数 2.10节. 显示一个通知窗口 2.11节. 使用Calendar控件 2.12节. 弹出窗口的显示和位置 2.13节. 自定义弹...

    C++标准程序库STL的架构

    2.6 命名空间 4 2.7 using声明 4 2.8 namespace std 4 2.9 explicit关键字 5 2.10 新的类型转换符 5 2.11 静态常量成员的初始化 6 2.12 时间复杂度O记号 6 3 一般概念 7 3.1 头文件 7 3.2 错误处理和异常处理 7 ...

Global site tag (gtag.js) - Google Analytics