Effective Java 第二版 学习笔记(4) 消除过期对象的引用 避免使用终结方法

参考:Effective Java 第二版 第二章

消除过期对象的引用

过期引用是指永远不会再被解除引用。

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

内存泄漏的一个来源是缓存,一旦把对象放到缓存中,就很容易被遗忘掉,从而使得它不再有用之后仍然很长一段时间内留在缓存中。一种可能的解决方案是:只要在缓存之外存在对某个项键的引用,该项就有意义,那么就可以使用WeakHashMap代表缓存,当缓存中的项过期之后,它们就会被自动删除。记住只有当所要缓存的项的生命周期是由该键的外部引用而不是由值决定时,WeakHashMap才有用。

内存泄漏的另一个来源是监听器和其他回调。如果实现了一个API,客户端在这个API中注册回调,却没有显式地取消注册,除非采取某些动作,否则就会积聚。确保回调立即被当做垃圾回收的最加方法就是只保存它们的弱引用。

避免使用终结方法

终结方法通常是不可预测的,也是很危险的,一般情况下是不必要的。使用终结方法会导致行为不稳定、降低性能,以及可移植性问题。终结方法的缺点在于不能保证会被及时的执行。从一个对象变得不可到达开始到它的终结方法被执行,所花费的时间是任意长的。注重时间的任务不该由终结方法来完成。

及时地执行终结方法是垃圾回收算法的一个重要功能,这种算法在不同的JVM实现中大相径庭。

Java语言规范不仅不保证终结方法会被及时地执行,而且根本就不保证它们会被执行。不应该依赖终结方法来更新重要的持久状态。唯一声称保证终结方法被执行的是Systtem.runFinalizersOnExit,以及Runtime.runFinalizersOnExit。这两个方法都有致命的缺陷,已经被废弃了。

如果未被捕获的异常在终结过程中被抛出来,那么这种异常可以被忽略,并且该对象的终结过程也会被终止。

使用终结方法会有一个非常严重的性能损失。

显式的终止方法通常与try-finally结构结合起来使用,以确保及时终止。

终结方法的合法用途是:当对象所有者忘记调用显式终止方法时,终结方法可以充当安全网。第二种合理用途与对象的本地对等体有关。

本地对等体是一个本地对象,普通对象通过本地方法委托给一个本地对象。因为本地对等体不是一个普通对象,所以垃圾回收器不会知道它,当它的Java对等体被回收的时候,它不会被回收。在本地对等体并不拥有关键资源的前提下,终结任务正是执行这项任务的最合适的工具。如果本地对等体拥有必须被及时终止的资源,那么该类就应该具有一个显式的终止方法。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券