了解 Java 的 Reference 类:SoftReference、WeakReference 和 PhantomReference

发布于 2024-09-11 11:24:49 字数 671 浏览 5 评论 0原文

有人可以解释这三个参考类之间的区别(或发布一个很好的解释链接)吗? 软引用 > 弱引用 > 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 是否为 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

动听の歌 2024-09-18 11:24:49

Java 库 的文档>java.lang.ref package 表征了三种显式引用类型的强度递减。

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

相比之下,当您不想影响引用对象的生命周期时,请使用WeakReference;您只想对引用的对象进行单独的断言,只要它保持活动状态即可。对象的收集资格不受绑定弱引用的存在的影响。类似从对象实例到相关属性的外部映射(其中只要相关对象处于活动状态就需要记录该属性)是 WeakReferenceWeakHashMap 的一个很好的用途>。

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

在您的示例代码中, ref 引用(或者,如果您愿意,“变量”)不能为 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.
}

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 a SoftReference 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 bound WeakReferences. 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 for WeakReferences and WeakHashMap.

The last one—PhantomReference—is harder to characterize. Like WeakReference, such a bound PhantomReference exerts 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 PhantomReference gets queued in its related ReferenceQueue. Normally one derives a type from PhantomReference 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 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:

final String val = ref.get();
if (null != val)
{
  // "val" is now pinned strongly.
}
else
{
  // "val" is already ready to be collected.
}
不知所踪 2024-09-18 11:24:49

链接: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 as get always returns null 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 the Reference 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.

吻风 2024-09-18 11:24:49

还应该提到,正如 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.

巡山小妖精 2024-09-18 11:24:49
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() 的调用在这里很重要。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文