`

消除过期的对象引用

阅读更多

下面这段程序存在一个“内存泄漏”。在极端的情况下,会导致磁盘交换(Disk Paging),甚至导致程序失败(OutOfMemoryError)。
那么哪里引起的内存泄漏呢?
如果一个栈先是增长,然后再收缩,那么从栈中弹出来的对象讲不会被当做垃圾回收,即使使用的栈程序不再引用这些对象。
这是因为,栈内部维护着对这些对象的过期引用(obsolete reference)。过期引用是指,永远也不会再被接触的引用。
demo:

  1. // Can you spot the "memory leak"?  
  2.   
  3. import java.util.*;  
  4.   
  5. public class Stack {  
  6.     private Object[] elements;  
  7.     private int size = 0;  
  8.     private static final int DEFAULT_INITIAL_CAPACITY = 16;  
  9.   
  10.     public Stack() {  
  11.         elements = new Object[DEFAULT_INITIAL_CAPACITY];  
  12.     }  
  13.   
  14.     public void push(Object e) {  
  15.         ensureCapacity();  
  16.         elements[size++] = e;  
  17.     }  
  18.   
  19.     public Object pop() {  
  20.         if (size == 0)  
  21.             throw new EmptyStackException();  
  22.         return elements[--size];  
  23.     }  
  24.   
  25.     /** 
  26.      * Ensure space for at least one more element, roughly 
  27.      * doubling the capacity each time the array needs to grow. 
  28.      */  
  29.     private void ensureCapacity() {  
  30.         if (elements.length == size)  
  31.             elements = Arrays.copyOf(elements, 2 * size + 1);  
  32.     }  
  33. }  

修复的方法:
一旦对象引用已经过期,只需清空这些引用即可。
   

  1. public Object pop() {  
  2.     if (size == 0)  
  3.         throw new EmptyStackException();  
  4.     Object result = elements[--size];  
  5.     elements[size] = null//Eliminate obsolete reference     
  6.     return result;  
  7. }  


当然也没必要谨慎的将所有不用的东西设置为null。
清空对象引用应该是一种例外,而不是一种规范行为。
消除过期引用最好的方法是让包含该引用的变量结束其生命周期。
那么,合适应该清空引用呢?
问题在于,Stack类自己管理内存。存储池包含了elements数组的元素。数组活动区域中的元素是已分配的,而数组其余部分的元素则是自由的。
但是对于垃圾回收器而言,elements数组中的所有对象引用都同等有效。
一旦数组元素变成了非活动部分的一部分,程序员就收工清空这些数组元素。


只要类是自己管理内存,程序员就应该警惕内存泄漏问题。

 

内存泄漏的另一个常见来源是缓存。

 

LinkedHashMap类的removeEldestEntry(Map.Entry<K,V> eldest) 此方法非常有用:它允许映射通过删除旧条目来减少内存损耗。 

内存泄漏的第三个常见来源是监听器和其他回调。
如果你实现了一个API,客户端在这个API中注册回调,却没有显示的取消注册,那么除非你采取某些动作,否则他们就会积聚。
最佳方法是只保存他们的弱引用(weak reference),例如,只将他们保存为WeakHashMap中键。

可借助于Heap剖析工具(Heap Profiler)发现内存泄漏问题。

分享到:
评论

相关推荐

    effective java 读书笔记

    - Item6:消除过期对象引用,避免内存泄漏。及时将不再使用的对象设置为null,使其可以被垃圾收集器回收。 3. **处理对象生命周期** - Item7:Java中的finalizers用于清理对象资源,但不应依赖其执行,因为它们...

    《Effective Java》读书分享.pptx

    消除过期的对象引用 消除过期引用是非常重要的,不仅可以减少内存占用,还可以避免对象泄露和内存溢出。消除过期引用可以使用多种方法,例如,使用 WeakReference 或 SoftReference,或者使用 finalize() 方法来...

    Java弱引用与WeakHashMap

    在《Effective Java 2nd Edition》中,第6条“消除过期的对象引用”提到,虽然Java有垃圾回收机制,但是只要是自己管理的内存,应该警惕内存泄露的问题,例如的对象池、缓存中的过期对象都有可能引发内存泄露的问题...

    JS脚本运行缺少对象

    2. **清除浏览器缓存**:浏览器缓存中可能存在损坏的文件或过期的数据,清理缓存有助于消除这些潜在的问题。 3. **检查病毒感染**:病毒或恶意软件可能干扰正常的脚本执行,使用反病毒软件进行全面扫描是必要的。 4....

    effectice_java第二版 英文

    6. **条目6:消除过期的对象引用(Eliminate Unused Object References)** 过期的对象引用可能导致内存泄漏,确保及时释放不再使用的对象。 7. **条目7:覆盖equals时总要覆盖hashCode(Override equals() and ...

    Java高效编程指南.doc

    - **避免创建重复对象**:消除对过期对象的引用,一旦对象不再需要,应立即清除资源和引用,防止内存泄漏。 2. **对象定义** - **equals方法的重载**:当类需要实现逻辑等价测试时,应重载equals方法,确保与...

    Quest JProbe教程:Java内存分析示例(节选)

    LeakExample程序旨在演示如何定位一个过期集合引用所导致的Java堆中整个对象树的游离问题。通过本教程,开发者将学会如何使用JProbe来识别代码中的游离对象,并采取措施修复这些问题。 ##### 3.2 操作步骤 ###### ...

    Java内存泄漏原因分析大全

    例如,如果程序中存在对不再需要的对象的引用,那么这些对象将不会被垃圾回收器清理掉,从而导致内存泄漏。 #### 典型的内存泄漏原因 ##### 1. 全局集合的不当管理 在大型应用中,常常需要使用全局集合(例如JNDI...

    move

    1. 右值引用:这是实现移动语义的关键,它允许函数参数捕获临时对象或即将过期的对象。用`&&`符号表示,如`T&& obj`。 2. 移动构造函数:当一个新对象通过另一个即将销毁的对象创建时,移动构造函数会被调用。它将...

    C#错误编码详解很有用!

    **解决方案**: 消除命名空间内的命名冲突。 #### 错误 CS0105 **描述**: 使用了已过期的类型。 **解决方案**: 替换为有效的类型。 #### 错误 CS0106 **描述**: 属性值不在当前范围内有效。 **解决方案**: 确认属性...

    2021-2022计算机二级等级考试试题及答案No.1341.docx

    - **实际应用**:利用MySQL事件可以实现定时任务的自动化处理,如定期备份数据、清理过期记录等。 #### 4. 软件分类 - **知识点说明**:软件可以分为应用软件、系统软件和支持软件(或工具软件)。其中,教务管理...

    微软活动目录管理管理简明手册

    b+ v+ T d/ R在活动目录中每个对象都有一个标识名,标识名确定了对象所在的域和可以找到对象的完整路径。比如,典型的标识名包括: ) v( ^# h2 Q% P ) k( @' h3 e4 k* G+ s" i7 `CN=TOM,OU=Manager,DC=Tech,DC=...

    JAVA核心知识点整理(有效)

    引用计数法............................................................................................................................................... 26 2.4.1.2. 可达性分析..........................

Global site tag (gtag.js) - Google Analytics