前几天发了一篇关于垃圾收集的帖子,自己也不是这方面的专家,所以肯定有很多问题和错误,也请大家多多包涵和指教。
今天再进一步谈一下这个几个Reference吧。老实说,这几个名词我也是最近才听说,平时也没有实际使用过,但是确实在java 1.2就存在的,看来真的是学无止境啊。
在《Thinking in Java》第四版是如此描述:In the order of SoftReference, WeakReference, and PhantomReference, each one is "weaker" than the last and corresponds to a different level of reachability. Soft references are for implementing memory-sensitive caches. Weak references are for implementing "canonicalizing mappings"—where instances of objects can be simultaneously used in multiple places in a program, to save storage—that do not prevent their keys (or values) from being reclaimed. Phantom references are for scheduling pre-mortem cleanup actions in a more flexible way than is possible with the Java finalization mechanism.
在引入了这几个引用之后,对象的生命周期【1】:
import java.lang.ref.*; public class References { public static void main(String[] args) { Object softObj, weakObj, phantomObj; Reference ref; WeakReference weakRef; SoftReference softRef; PhantomReference phantomRef; ReferenceQueue softQueue, weakQueue, phantomQueue; softObj = new String("Soft Reference"); weakObj = new String("Weak Reference"); phantomObj = new String("Phantom Reference"); softQueue = new ReferenceQueue(); weakQueue = new ReferenceQueue(); phantomQueue = new ReferenceQueue(); softRef = new SoftReference(softObj, softQueue); weakRef = new WeakReference(weakObj, weakQueue); phantomRef = new PhantomReference(phantomObj, phantomQueue); // Print referents to prove they exist. Phantom referents // are inaccessible so we should see a null value. System.out.println("Soft Referenc: "+ softRef.get()); System.out.println("Weak Reference: " + weakRef.get()); System.out.println("Phantom Reference: " + phantomRef.get()); // Clear all strong references softObj = null; weakObj = null; phantomObj = null; // Reach object via reference System.out.println("Soft Referenc: "+ softRef.get()); System.out.println("Weak Reference: " + weakRef.get()); System.out.println("Phantom Reference: " + phantomRef.get()); // Check the queue before garbage collection System.out.println("Soft Queued: "+ softRef.isEnqueued()); System.out.println("Weak Queued: " + weakRef.isEnqueued()); System.out.println("Phantom Queued: " + phantomRef.isEnqueued()); // Invoke garbage collector in hopes that references will be queued System.gc(); // Try to finalize the phantom references if not already if (!phantomRef.isEnqueued()) { System.out.println("Requestion finalization."); System.runFinalization(); } // See if the garbage collector has queued the references System.out.println("Soft Queued: "+ softRef.isEnqueued()); System.out.println("Weak Queued: " + weakRef.isEnqueued()); System.out.println("Phantom Queued: " + phantomRef.isEnqueued()); try { // Test soft reference if(softRef.isEnqueued()){ System.out.println("Soft Referenc in the Queue"); ref = softQueue.remove(); System.out.println("Soft Queued: "+ ref.get()); } else{ System.out.println("Soft Referenc not in the Queue"); } // Test weak reference if(weakRef.isEnqueued()){ System.out.println("Weak Referenc in the Queue"); ref = weakQueue.remove(); System.out.println("Weak Reference: " + ref.get()); } else{ System.out.println("Weak Referenc not in the Queue"); } // Test Phantom reference if(phantomRef.isEnqueued()){ System.out.println("Phantom Referenc in the Queue"); ref = phantomQueue.remove(); System.out.println("Phantom Reference: " + ref.get()); // We have to clear the phantom referent even though // get() returns null ref.clear(); } else{ System.out.println("Phantom Referenc not in the Queue"); } } catch (InterruptedException e) { e.printStackTrace(); return; } } }
上面这段代码演示了几种引用的特性:
下面这个例子来自《Thinking in Java》第四版,稍作修改:
//: containers/References.java //Demonstrates Reference objects from <Thinking in Java> 4th edition section "Holding references" import java.lang.ref.*; import java.util.*; class VeryBig { private static final int SIZE = 10000; private long[] la = new long[SIZE]; private String ident; public VeryBig(String id) { ident = id; } public String toString() { return ident; } public String getID() { return ident; } protected void finalize() { System.out.println("Finalizing " + ident); } } public class ReferencesTIJ { private static ReferenceQueue<VeryBig> rq = new ReferenceQueue<VeryBig>(); public static void checkQueue() { Reference<? extends VeryBig> inq = rq.poll(); referenceType(inq); } private static void referenceType(Reference<? extends VeryBig> inq) { if (inq != null) { if (inq instanceof PhantomReference) System.out.println("PhantomReference In queue: " + inq.get()); if (inq instanceof WeakReference) System.out.println("WeakReference In queue: " + inq.get()); if (inq instanceof SoftReference) System.out.println("SoftReference In queue: " + inq.get()); } } public static void main(String[] args) { int size = 10; // Or, choose size via the command line: if (args.length > 0) size = new Integer(args[0]); LinkedList<SoftReference<VeryBig>> sa = new LinkedList<SoftReference<VeryBig>>(); for (int i = 0; i < size; i++) { sa.add(new SoftReference<VeryBig>(new VeryBig("Soft " + i), rq)); System.out.println("Just created <" + i + "> : " + sa.getLast().toString()); checkQueue(); } LinkedList<WeakReference<VeryBig>> wa = new LinkedList<WeakReference<VeryBig>>(); for (int i = 0; i < size; i++) { wa.add(new WeakReference<VeryBig>(new VeryBig("Weak " + i), rq)); System.out.println("Just created <" + i + "> : " + wa.getLast().toString()); checkQueue(); } SoftReference<VeryBig> s = new SoftReference<VeryBig>(new VeryBig( "Soft Last")); WeakReference<VeryBig> w = new WeakReference<VeryBig>(new VeryBig( "Weak Last")); System.gc(); LinkedList<PhantomReference<VeryBig>> pa = new LinkedList<PhantomReference<VeryBig>>(); for (int i = 0; i < size; i++) { pa.add(new PhantomReference<VeryBig>(new VeryBig("Phantom " + i), rq)); System.out.println("Just created <" + i + "> : " + pa.getLast()); } //System.runFinalization(); Reference<? extends VeryBig> ref; while ((ref = rq.poll()) != null) { if (ref != null) { referenceType(ref); } } } }
这个例子比较有意思,每次执行,结果都会有一些差异。至于为什么,我也在研究之中,欢迎大家指教!
参考:
【1】http://www.kdgregory.com/index.php?page=java.refobj
【2】http://improving.iteye.com/blog/436311