【问题标题】:Understanding Java's Reference classes: SoftReference, WeakReference, and PhantomReference了解 Java 的引用类:SoftReference、WeakReference 和 PhantomReference
【发布时间】:2011-03-20 18:30:32
【问题描述】:

有人可以解释三个参考类之间的区别(或发布一个很好的解释的链接)吗? SoftReference > WeakReference > PhantomReference,但我什么时候会使用每一个?为什么有WeakHashMap 而没有SoftHashMap 或PhantomHashMap?

如果我使用以下代码...

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 课程...谢谢!

【问题讨论】:

  • 为什么有WeakHashMap 而没有SoftHashMap 或PhantomHashMap 很好的问题,为什么我以前没有注意到这个......??
  • ref != null 检查没有意义。 ref 永远不会是 null。
  • 添加到 Q:strongRef --&gt; weakRef --&gt; objA。现在,objA 是否会被 GC,因为它有来自 strongRef 的间接引用。

标签: java reference weak-references phantom-reference soft-references


【解决方案1】:

Java 库documentation for the java.lang.ref package 描述了三种显式引用类型的递减强度。

当您希望被引用的对象保持活动状态直到主机进程内存不足时,您可以使用SoftReference。在收集器需要释放内存之前,该对象将不符合收集条件。简单地说,绑定 SoftReference 意味着“固定对象,直到你不能再使用为止。”

相比之下,当您不想影响被引用对象的生命周期时,请使用WeakReference;您只想对引用的对象进行单独的断言about,只要它仍然存在。对象的收集资格不受绑定WeakReferences 存在的影响。像从对象实例到相关属性的外部映射,只要相关对象还活着,就需要记录属性,这对WeakReferences 和WeakHashMap 很有用。

最后一个——PhantomReference——更难描述。与WeakReference 一样,这样的绑定PhantomReference 不会影响被引用对象的生命周期。但与其他引用类型不同,甚至不能取消引用PhantomReference。从某种意义上说,就调用者所知,它并不指向它所指向的东西。它仅允许将一些相关数据与引用的对象相关联——当PhantomReference 在其相关的ReferenceQueue 中排队时,这些数据可以在以后进行检查和操作。通常从PhantomReference 派生一个类型,并在该派生类型中包含一些附加数据。不幸的是,使用这种派生类型需要进行一些向下转换。

在您的示例代码中,可以为 null 的不是 ref 引用(或者,如果您愿意,“变量”)。相反,调用Reference#get() 获得的值可能为空。如果发现为null,那就来不及了;被引用的对象已经在被收集的路上:

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

【讨论】:

  • 添加到 Q:strongRef --&gt; weakRef --&gt; objA。现在,objA 是否会被 GC,因为它有来自 strongRef 的间接引用。
  • 如果我正确理解您的问题,@samshers,objA 有资格作为垃圾收集。固定WeakReference 不会影响WeakReference 指向的对象。
  • 没有强大的参考价值链会有所作为。因为要对objA 进行垃圾收集,必须首先删除弱引用。强引用指向弱引用,使得弱引用没有资格被 GC
  • 不,不需要收集WeakReference 就可以收集objA。 WeakReference 不会保持 objA 活着。相反,它是一种在 objA 还活着的时候找到它的方法——不影响它的生命周期——并检测收集器何时已经把它拿走了。
【解决方案2】:

链接:https://community.oracle.com/blogs/enicholas/2006/05/04/understanding-weak-references

PhantomHashMap 不能很好地工作,因为 get 总是返回 null 以获得幻像引用。

缓存很困难,所以SoftHashMap 可能没有你想象的那么好。不过,我相信 Google 的收藏库包含一个通用的参考地图实现。

您应该始终检查get 是否返回非null。 (请注意,不检查 Reference 引用本身是否不是-null。)对于实习字符串,它总是会,但(一如既往)不要试图“聪明”地处理它。

【讨论】:

  • 链接已过期。
  • @MehrajMalik 链接已修复。
  • 添加到 Q:strongRef --&gt; weakRef --&gt; objA。现在,objA 是否会被 GC,因为它有来自 strongRef 的间接引用。
【解决方案3】:

还应该提到,正如 Truong Xuan Tinh 的评论所述,这里:http://blog.yohanliyanage.com/2010/10/ktjs-3-soft-weak-phantom-references/

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

【讨论】:

    【解决方案4】:
    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() 的调用在这里很重要。

    【讨论】:

      猜你喜欢
      • 2010-09-22
      • 2011-12-03
      • 1970-01-01
      • 2011-09-25
      • 2010-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多