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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3329691/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 22:13:46  来源:igfitidea点击:

Understanding Java's Reference classes: SoftReference, WeakReference, and PhantomReference

javareferenceweak-referencesphantom-referencesoft-references

提问by Haywood Jablomey

Can someone explain the difference between the three Reference classes (or post a link to a nice explanation)? SoftReference> WeakReference> PhantomReference, but when would I use each one? Why is there a WeakHashMapbut no SoftHashMapor PhantomHashMap?

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

And if I use the following code...

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

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?!
}

...what happens? Do I have to check if refis null before every statement (this is wrong, but what shouldI do)? Sorry for the rapid-fire questions, but I'm having trouble understanding these Referenceclasses... Thanks!

...发生什么了?我一定要检查是否ref为空每个语句之前(这是不对的,但什么应该怎么办)?很抱歉快速提问,但我无法理解这些Reference课程......谢谢!

回答by Tom Hawtin - tackline

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

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

PhantomHashMapwouldn't work very well as getalways returns nullfor phantom references.

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

Caches are difficult, so SoftHashMapmight not work as well as you might think. However, I believe Google's collection library contains a general reference map implementation.

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

You should always check that getreturns non-null. (Note, that not checking that the Referencereference itself is not-null.) In the case of interned strings it always will, but (as ever) don't try to be "clever" about it.

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

回答by seh

The Java library documentation for the java.lang.refpackagecharacterizes the decreasing strength of the three explicit reference types.

的 Java 库文档java.lang.ref描述了三种显式引用类型的强度递减。

You use a SoftReferencewhen you want the referenced object to stay alive until the host process is running low on memory. The object will not be eligible for collection until the collector needsto free memory. Loosely stated, binding a SoftReferencemeans, "Pin the object until you can't anymore."

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

By contrast, use a WeakReferencewhen you don't want to influence the referenced object's lifetime; you merely want to make a separate assertion aboutthe referenced object, so long as it remains alive. The object's eligibility for collection is not influenced by the presence of bound WeakReferences. Something like a an external mapping from object instance to related property, where the property need only be recorded so long as the related object is alive, is a good use for WeakReferences and WeakHashMap.

相比之下,WeakReference当您不想影响引用对象的生命周期时使用 a ;你只是想制作一个单独的断言关于引用的对象,只要它仍然活着。对象的收集资格不受 bound WeakReferences 的影响。类似于从对象实例到相关属性的外部映射,只要相关对象还活着,就需要记录该属性,这对于WeakReferences 和 来说是一个很好的用途WeakHashMap

The last one—PhantomReference—is harder to characterize. Like WeakReference, such a bound PhantomReferenceexerts no influence on the referenced object's lifetime. But unlike the other reference types, one can't even dereference a PhantomReference. In a sense, it doesn't point to the thing it points to, as far as callers can tell. It merely allows one to associate some related data with the referenced object -- data that can later be inspected and acted upon when the PhantomReferencegets queued in its related ReferenceQueue. Normally one derives a type from PhantomReferenceand includes some additional data in that derived type. Unfortunately, there's some downcasting involved to make use of such a derived type.

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

In your example code, it's not the refreference (or, if you prefer, "variable") that can be null. Rather, it's the value obtained by calling Reference#get()that may be null. If it is found to be null, you're too late; the referenced object is already on its way to being collected:

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

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

回答by James L

It should also be mentioned, as stated on the comment by Truong Xuan Tinh, here: http://blog.yohanliyanage.com/2010/10/ktjs-3-soft-weak-phantom-references/

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

That JRockit JVM implements weak/soft/phantom references differently than Sun JVM.

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

回答by kopite

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());
}

In this case, it will output null. The call to System.gc()is important here.

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