了解 Java 的 Reference 类:SoftReference、WeakReference 和 PhantomReference
有人可以解释这三个参考类之间的区别(或发布一个很好的解释链接)吗? 软引用
> 弱引用
> 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
是否为 null(这是错误的,但我应该做什么)?很抱歉提出了一些快速问题,但我无法理解这些Reference
类...谢谢!
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 WeakHashMap
but no SoftHashMap
or PhantomHashMap
?
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 ref
is null before every statement (this is wrong, but what should I do)? Sorry for the rapid-fire questions, but I'm having trouble understanding these Reference
classes... Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Java 库
的文档>java.lang.ref
package 表征了三种显式引用类型的强度递减。当您希望引用的对象保持活动状态直到主机进程内存不足时,您可以使用
SoftReference
。在收集器需要释放内存之前,该对象不符合收集条件。宽松地说,绑定 SoftReference 意味着“固定对象,直到无法再固定为止”。相比之下,当您不想影响引用对象的生命周期时,请使用
WeakReference
;您只想对引用的对象进行单独的断言,只要它保持活动状态即可。对象的收集资格不受绑定弱引用的存在的影响。类似从对象实例到相关属性的外部映射(其中只要相关对象处于活动状态就需要记录该属性)是WeakReference
和WeakHashMap
的一个很好的用途>。最后一个 -
PhantomReference
- 更难描述。与WeakReference
一样,此类绑定的PhantomReference
对引用对象的生命周期没有影响。但与其他引用类型不同的是,我们甚至无法取消对 PhantomReference 的引用。从某种意义上说,就调用者所知,它并不指向它所指向的东西。它仅允许将一些相关数据与引用的对象关联起来,这些数据稍后可以在 PhantomReference 在其相关的 ReferenceQueue 中排队时进行检查和操作。通常,人们会从 PhantomReference 派生出一种类型,并在该派生类型中包含一些附加数据。不幸的是,使用这种派生类型需要进行一些向下转型。在您的示例代码中,
ref
引用(或者,如果您愿意,“变量”)不能为 null。相反,它是通过调用Reference#get()
可能为 null。如果发现为空,那就太晚了;引用的对象已经在被收集的路上:The Java library documentation for the
java.lang.ref
package characterizes the decreasing strength of the three explicit reference types.You use a
SoftReference
when 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 needs to free memory. Loosely stated, binding aSoftReference
means, "Pin the object until you can't anymore."By contrast, use a
WeakReference
when you don't want to influence the referenced object's lifetime; you merely want to make a separate assertion about the referenced object, so long as it remains alive. The object's eligibility for collection is not influenced by the presence of boundWeakReference
s. Something like 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 forWeakReference
s andWeakHashMap
.The last one—
PhantomReference
—is harder to characterize. LikeWeakReference
, such a boundPhantomReference
exerts no influence on the referenced object's lifetime. But unlike the other reference types, one can't even dereference aPhantomReference
. 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 thePhantomReference
gets queued in its relatedReferenceQueue
. Normally one derives a type fromPhantomReference
and includes some additional data in that derived type. Unfortunately, there's some downcasting involved to make use of such a derived type.In your example code, it's not the
ref
reference (or, if you prefer, "variable") that can be null. Rather, it's the value obtained by callingReference#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:链接:https://community.oracle.com /blogs/enicholas/2006/05/04/understanding-weak-references
PhantomHashMap
不能很好地工作,因为get
总是返回null< /code> 用于虚拟引用。
缓存很困难,因此 SoftHashMap 可能不会像您想象的那样工作。然而,我相信谷歌的集合库包含一个通用的参考地图实现。
您应该始终检查
get
返回非null
。 (请注意,不检查Reference
引用本身是否为null
。)在内部字符串的情况下,它总是会,但(一如既往)不要尝试对此要“聪明”。A link: https://community.oracle.com/blogs/enicholas/2006/05/04/understanding-weak-references
PhantomHashMap
wouldn't work very well asget
always returnsnull
for phantom references.Caches are difficult, so
SoftHashMap
might not work as well as you might think. However, I believe Google's collection library contains a general reference map implementation.You should always check that
get
returns non-null
. (Note, that not checking that theReference
reference itself is not-null
.) In the case of interned strings it always will, but (as ever) don't try to be "clever" about it.还应该提到,正如 Truong Xu Tinh 的评论所述,此处:http://blog.yohanliyanage.com/2010/10/ktjs-3-soft-weak-phantom-references/
JRockit JVM 实现弱/软/幻像引用的方式与 Sun JVM 不同。
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/
That JRockit JVM implements weak/soft/phantom references differently than Sun JVM.
在这种情况下,它将输出 null。对 System.gc() 的调用在这里很重要。
In this case, it will output null. The call to
System.gc()
is important here.