了解Java的引用类:SoftReference,WeakReference和PhantomReference

有人可以解释三个参考类之间的差异(或链接到一个很好的解释)? SoftReference > WeakReference > PhantomReference ,但是什么时候使用每个? 为什么有一个WeakHashMap但没有SoftHashMapPhantomHashMap

如果我使用下面的代码…

 WeakReference<String> ref = new WeakReference<String>("Hello!"); if (ref != null) { // ref can get collected at any time... System.gc(); // Let's assume ref gets collected here. System.out.println(ref.get()); // Now what?! } 

…怎么了? 每次发言之前,我是否需要检查ref是否为空(这是错误的,但是我应该怎么做)? 对不起,快速的问题,但我无法理解这些Reference类…谢谢!

java.lang.ref包的Java库文档描述了三个显式引用types的递减强度。

如果希望引用的对象保持活动状态,则使用SoftReference ,直到主机进程内存不足。 在收集器需要释放内存之前,该对象将不符合收集条件。 松散地指出,绑定一个SoftReference意味着“固定对象,直到你不能再。”

相比之下,如果您不想影响引用对象的生命周期,请使用WeakReference ; 你只是想被引用的对象作一个单独的断言,只要它仍然活着。 该对象的收集资格不受绑定的WeakReference的存在的影响。 类似于从对象实例到相关属性的外部映射,只要相关对象处于活动状态,该属性只需要被logging下来,这对于WeakReferenceWeakHashMap来说是非常有用的。

最后一个 – PhantomReference – 更难描述。 像WeakReference一样,这个绑定的PhantomReference对引用的对象的生命周期没有影响。 但与其他引用types不同,甚至无法解引用PhantomReference 。 从某种意义上讲,它并不指向它指向的东西,就呼叫者而言。 它只允许将一些相关的数据与被引用的对象相关联 – 当PhantomReference在其相关的ReferenceQueue排队时,可以稍后检查和操作这些数据。 通常从PhantomReference派生一个types,并在派生types中包含一些附加数据。 不幸的是,使用这种派生types涉及到一些向下转换。

在您的示例代码中,它不是ref引用(或者,如果您愿意的话,“variable”)可以为null。 而是通过调用Reference#get()得到的值可能为null。 如果发现它是空的,你太迟了; 被引用的对象已经被收集起来了:

 final String val = ref.get(); if (null != val) { // "val" is now pinned strongly. } else { // "val" is already ready to be collected. } 

链接: http : //weblogs.java.net/blog/enicholas/archive/2006/05/understanding_w.html

PhantomHashMap不能很好地工作,因为对于幻影引用, get总是返回null

caching很困难,所以SoftHashMap可能无法像您想象的那样工作。 不过,我相信Google的collections库包含一个通用的参考地图实现。

你应该总是检查get返回非null 。 (注意,不检查Reference引用本身是否为null )。对于实例化的string,它始终如此,但是(一如既往)不要试图对其进行“聪明”操作。

还应该提到,正如Truong Xuan Tinh在评论中所说的那样: http : //blog.yohanliyanage.com/2010/10/ktjs-3-soft-weak-phantom-references/

JRockit JVM以不同于Sun JVM的方式实现弱/软/幻像引用。

  String str = new String("hello, world"); WeakReference<String> ref = new WeakReference<String>(str); str = null; if (ref != null) { System.gc(); System.out.println(ref.get()); } 

在这种情况下,它将输出null。 而System.gc()在这里很重要。