《Effective java》读书笔记——过期引用

过期引用,指永远也不会再被解除的引用。
栈的pop函数的一般实现:
<span style="font-size:18px;">     public Object pop() {
            if ( size == 0)
                 throw new EmptyStackException();
            // 上面的过期已用没有清除,所以会发生内存泄露
            return elements [--size ];
     }</span>

由于pop只是将栈顶标识下移,而并没有释放栈中相应位置的对象,所以栈中有效范围外的对象仍在存在,并不会被Gc释放,所以会造成内存泄露。要解决这种问题,需要在每次对象引用过期时,清空引用
<span style="font-size:18px;">     public Object pop() {
            if ( size == 0)
                 throw new EmptyStackException();
            elements[ size]= null;
            return elements[-- size];
     }</span>

清空对象引用应该是一种例外,而不是一种规范行为。只在需要的地方清空过期引用。一般而言,只要类是自己管理内存,程序员就应该警惕内存泄露问题
内存泄露Example:
(1)栈就是其中的一个例子,栈管理一个内存数组,其中包括只有栈能识别的有效区域数据和无效数据,而整个内存数组的所有引用对于Gc来讲都是等效的,所以需要程序员告诉Gc哪些数据是不重要的,便于Gc清理。
(2)缓存:缓存项随着时间的推移需要清理掉没用的项(只要该键值没有对应的外部引用时就清理掉),实现方式有三种:一是通过Gc自动清理弱引用的机制,WeakHashMap(键对象间接的存储为一个弱引用的指示对象),当某个键不再正常使用时将自动移除其条目。更精确地说,对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的丢弃,这就使该键成为可终止的,被终止,然后被回收。二是在给缓存添加新条目的时候顺便进行清理,LinkedHashMap就是利用removeEldestEntry()方法实现的;三是自定义一个后台线程(Timer或者ScheduledThreadPoolExector)来完成。
(3)监听器和回调:如果用户不断注册回调,却没有显示的取消回调就会造成内存泄露。最好只保存回调的弱引用,如将它们保存成WeakHashMap中的键。对于该段话的理解如下:来源(http://stackoverflow.com/questions/2859464/how-to-avoid-memory-leaks-in-callback
To illustrate the concept with a quick (crude) example, consider the following:
 
                 public interface ChangeHandler {
                    public void handleChange();
                 }

                 public class FileMonitor {

                    private File file;
                    private Set< ChangeHandler> handlers = newHashSet<ChangeHandler>();

                    public FileMonitor( File file) {
                        this .file = file;
                    }

                    public voidregisterChangeHandler(ChangeHandler handler) {
                        this .handlers.add(handler);
                    }

                    public voidunregisterChangeHandler(ChangeHandler handler) {
                        this .handlers.remove(handler);
                    }

                    ...
                }

  If  a   client  class  then uses  this  FileMonitor  API they  might  do   this :  
                public class MyClass {

                    File myFile = new File( ...);
                    FileMonitor monitor = new FileMonitor(myFile );

                    public void something() {
                        ...
                        ChangeHandler myHandler = getChangeHandler();
                        monitor.registerChangeHandler(myHandler);
                        ...
                    }
                }

     If the author of the MyClass then forgets to call unregisterChangeHandler() when it's done with the handler, the FileMonitor' s HashSet will forever reference the instance that was registered, causing it to remain in memory until the FileMonitor is destroyed or the application quits.

     To prevent this, Bloch is suggesting using a weak-referencing collection instead of the HashSet, so that if your instance of MyClass isdestroyed, the reference will be removed from the monitor's collection.

     You might replace the HashSet in FileMonitor with a WeakHashMap and use the handlers as the keys, since the latter will automatically remove the  handler from the collection when all other references to the object are gone .
           





















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值