JAVA中的测不准原理
想做一个物理实验,看看某物质的导电情形,于是接上电压,并串联上一个安培计来观察电流,但是你知道吗? 安培计本身也带有电阻,造成你的实验准确度受到影响。诸如此类的问题在科学界很常见,所以有了「测不准原理」之说。不只是物理,测不准的现象在计算机上也有可能发生。比方说,你想写一个观察程序,观察 CPU 在执行某程序之下的使用率, 但是你的观察程序本身也会占用一部份的 CPU 效能,造成测出来的数据不精确。
再想象下面的情况:如果你想写一个 Java 程序,观察某对象什么时候会被垃圾收集的执行绪清除,所以你必须要用 一个 reference 记住此对象,以便随时观察,但是却因此造成此对象的 reference 数目一直无法为零, 使得对象无法被清除。...... 又是「测不准」。
java.lang.ref.WeakReference
不过,现在有了 Weak Reference 之后,这就可以迎刃而解了。如果你希望能随时取得某对象的信息,但又不想影响此 对象的垃圾收集,那么你应该用 Weak Reference 来记住此对象,而不是用一般的 reference。请看下面的例子:
...
WeakReference wr = new WeakReference(obj);
...
if (wr.get()==null) {
System.out.println("obj 已经被清除了 ");
} else {
System.out.println("obj尚未被清除,其信息是 "+obj.toString());
}
...
在此例中,透过 get() 可以取得此 Reference 的所指到的对象,如果传出值为 null 的话,代表此对象已经被清除。
这类的技巧,在设计 Optimizer 或 Debugger 这类的程序时常会用到,因为这类程序需要取得某对象的信息,但是不可以 影响此对象的垃圾收集。
java.lang.ref.SoftReference
Soft Reference 虽然和 Weak Reference 很类似,但是用途却不同。SoftReference 是用来设计 object-cache 之用的。 被 Soft Reference 指到的对象,即使没有任何 Direct Reference,也不会被清除。一直要到 JVM 内存不足时且 没有 Direct Reference 时才会清除,如此一来 SoftReference 不但可以把对象 cache 起来,也不会造成内存不足的错误 (OutOfMemoryError)。我觉得 Soft Reference 也适合拿来实作 pooling 的技巧。
java.lang.ref.PhantomReference
Phantom Reference 主要是用来取代对象的 finalize()。程序员利用 finalize() 来进行释放资源的同时,有可能不小心 让此对象再度拥有 Direct Reference。但是使用 Phantom Reference 则不会有此情形发生。和 Weak Reference 以 及 SoftReference 最大的不同是:Phantom Reference 一订要搭配着 ReferenceQueue 使用,因为 Phantom Reference 的 get() 传 出值一定是 null(以避免此对象不小心再度拥有 Direct Reference)。通常我们会设计一个 class 继承 PhantomReference,然 后 override 其 clear() 来定义释放资源等收尾的动作。当然,我宁可小心一点地使用 finalize(),也不愿意自找麻烦地使用 Phantom Reference。