Java:强/弱/弱/幻像参考之间的区别

164 java reference weak-references phantom-reference soft-references

我已经阅读了关于这个主题的这篇文章,但我真的不明白它.在描述概念时,请给我一些建议和示例.

Pao*_*sca 133

Java提供了两种不同类型/类的引用对象:.弱引用的对象可以被进一步划分成幻象.让我们一点一点地去吧.

强参考对象

StringBuilder builder = new StringBuilder();
Run Code Online (Sandbox Code Playgroud)

这是引用对象的默认类型/类,如果没有不同的指定:builder是一个强引用对象.这种引用使引用的对象不符合GC的条件.也就是说,只要一个对象被强引用对象链引用,就不能对其进行垃圾回收.

弱参考对象

WeakReference<StringBuilder> weakBuilder = new WeakReference<StringBuilder>(builder);
Run Code Online (Sandbox Code Playgroud)

弱引用对象不是引用对象的默认类型/类,要使用它们应该像上面的示例中那样明确指定.这种引用使参考对象符合GC的条件.也就是说,如果对于StringBuilder内存中的对象唯一可达的引用实际上是弱引用,则允许GC对StringBuilder对象进行垃圾收集.当内存中的对象只能由弱引用对象访问时,它将自动符合GC的条件.

弱点的程度

可以使用两种不同的弱点:柔和幻象.

一个柔软的参考对象基本上是保留在内存中多一点微弱的参考对象:通常情况下,它抵抗GC循环,直到内存可用,没有风险OutOfMemoryError(在这种情况下,它可以被删除).

另一方面,幻像参考对象仅用于确切地知道对象何时被有效地从内存中移除:通常它们用于修复奇怪的终结()复活/复活行为,因为它们实际上不返回对象本身但是只有帮助记录他们的记忆存在.

弱参考对象是实现缓存模块的理想选择.事实上,只要强引用链无法再访问对象/值,GC就可以实现一种自动驱逐.一个例子是WeakHashMap保留弱键.

  • 添加到 Q:`strongRef --&gt;weakRef --&gt; objA`。现在,`objA` 是否会被 GC,因为它有来自 `strongRef` 的间接引用。 (2认同)

Pun*_*Raj 73

弱参考:

简单地说,弱引用是一个不足以强迫对象保留在内存中的引用.弱引用允许您利用垃圾收集器为您确定可达性的能力,因此您不必自己执行此操作.

软参考:

软引用与弱引用完全相同,只是它不太愿意丢弃它引用的对象.一个只能弱到达的对象(对它的最强引用是WeakReferences)将在下一个垃圾收集周期被丢弃,但是一个可以轻松到达的对象通常会暂停一段时间.

幽灵参考:

幻像引用与SoftReference或WeakReference完全不同.它对它的对象的抓握是如此脆弱,你甚至无法检索对象 - 它的get()方法总是返回null.这种引用的唯一用途是跟踪它何时被引入ReferenceQueue,因为在那时你知道它指向的对象已经死了.

本文摘自:https://weblogs.java.net/blog/2006/05/04/understanding-weak-references

  • 为了记录,我宁愿生活在博客文章正确的世界里. (2认同)

Muh*_*rif 24

之间的简单的区别SoftReference,并WeakReference通过提供Android开发者.

a SoftReference和a 之间的差异WeakReference是决定清除和排列引用的时间点:

  • SoftReference应该尽可能晚地清除和排队A ,也就是说,万一VM存在内存不足的危险.

  • WeakReference一旦知道弱引用,就可以清除和排队A.


Sab*_*bya 16

您使用的三个术语主要与Object获取Garbage的资格相关.

弱引用 ::它的引用不足以强制对象保留在内存中.它是垃圾收集器为收集垃圾而收集该对象的想法. 您不能强制GC不收集它.

Soft Reference ::它或多或少像弱引用一样.但是你可以说它比垃圾收集中的弱引用更强烈地保存了对象.

如果垃圾收集器在第一个生命周期中收集弱引用,它将在下一个垃圾收集周期中收集软引用.

强引用 ::它与上述两种引用正好相反.他们不太喜欢收集垃圾(大多数情况下他们从未被收集过.)

您可以参考以下链接获取更多信息:

http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ref/Reference.html

  • 我认为这是错误的 - "如果垃圾收集器在第一个生命周期中收集弱引用,它将在下一个垃圾收集周期中收集软引用." 它不一定是这样的,你如何确保它们在GC的连续运行中出现?即使在第二次运行和第三次运行中,GC也可以允许软引用的对象存活.没有相关文档,如果有,请提及链接指定. (2认同)
  • 另外,您的答案有点模糊,看这句话(它或多或少都像弱引用一样)。但是可以说,它比垃圾回收中的弱引用更牢固地容纳了对象。-他显然是在询问差异而不是相似之处,所有这些词使该话题变得更加混乱而不是清晰。 (2认同)

小智 10

4度参考 - Strong, Weak, Soft, Phantom

强 - 是一种引用,使引用的对象不符合GC的条件.建造者课程.例如 - StringBuilder

弱 - 是符合GC条件的参考.

软 - 是一种参考,其对象符合GC的条件,直到内存可用.最适合图像缓存.它会保留它们直到记忆可用.

幻影 - 是一种参考,其对象直接符合GC的条件.仅用于了解何时从内存中删除对象.

用途:

  1. 允许您识别何时从内存中删除对象.

  2. finalize()方法重载时,GC可能不会及时地发生在两个类的GC符合条件的对象中.因此幻像引用使它们符合GC的条件finalize(),这就是为什么即使大多数堆都是垃圾也可以获得OutOfMemoryErrors的原因.

弱引用是实现缓存模块的理想选择.


Lav*_*ari 7

文章可以超有助于了解强,软,弱,虚引用。


为了给您一个总结,

如果您强烈引用某个对象,则该对象将永远无法由GC(垃圾收集器)收集/回收。

如果您仅对对象具有弱引用(而没有强引用),则该对象将在下一个GC周期被GC回收。

如果您仅具有对对象的软引用(没有强引用),则仅当JVM内存不足时,GC才会回收该对象。

我们为对象创建幻像引用,以跟踪该对象何时入队ReferenceQueue。一旦知道可以执行精细的终结处理。(这将使您免于意外复活该对象,因为幻影引用不会给您提供引用对象)。我建议你阅读文章以获得深入详细地介绍这一点。


因此,您可以说强引用具有最终的功能(GC永远无法收集)

软引用比弱引用强大(因为它们可以逃避GC周期,直到JVM内存不足)

弱引用甚至没有软引用强大(因为它们不能排除任何GC周期,如果对象没有其他强引用,则将被回收)。


餐厅类比

  • 服务员-GC
  • 您-堆中的对象
  • 餐厅面积/空间-堆空间
  • 新客户-在餐厅要桌子的新对象

现在,如果您是一个强大的客户(类似于强大的参考客户),那么即使有新客户进来餐厅或发生的事情,您也永远不会离开桌子(堆上的内存区域)。服务员无权告诉您(甚至要求您)离开餐厅。

如果您是一位软顾客(类似于软顾客),那么如果有新顾客进来,餐厅的服务员将不会要求您离开桌子,除非没有其他空桌子来容纳新顾客。(换句话说,服务员只会在有新客户进入并且没有其他可供该新客户使用的桌子时才要求您离开桌子)

如果您是弱顾客(类似于弱顾客),那么服务员可以(在任何时间)要求您离开餐厅:P

  • 妈的,现在我想听一个以“软引用来到酒吧……”开头的故事 (7认同)

Nar*_*shi 6

强大的参考

这些是您每天都会编写的常规对象引用:

Employee emp = new Employee();
Run Code Online (Sandbox Code Playgroud)

变量“EMP”保持的强引用Employee对象和可达通过强引用的任何链不符合垃圾收集的对象。通常,这是您想要的,但并非总是如此。现在,假设我们要从集合或映射中的数据库中获取很多员工,并且需要定期对其进行大量处理,因此,为了保持性能,我们会将其保留在缓存中。

至于这是好事,但现在我们需要不同的数据,我们不需要这些Employee对象和这些都不是从除缓存的任何地方引用。因为这些对象都没有使用,但仍然不符合垃圾收集这是造成内存泄漏和因为我们没有提及他们,我们无法从缓存中删除这些对象?因此,这里我们要么需要手动清空整个乏味的缓存,要么可以使用其他种类的引用,例如“弱引用”。

参考文献薄弱

弱引用不会将对象固定到内存中,如果未从其他引用中引用,则将在下一个GC周期中将其GC。我们可以用它Java提供的WeakReference类来创建上述种类的缓存,这将不会存储未从其他地方引用的对象。

WeakReference<Cache> cache = new WeakReference<Cache>(data);
Run Code Online (Sandbox Code Playgroud)

要访问数据,您需要调用cache.get()。如果弱引用是垃圾回收,则此get调用可能返回null:必须检查返回的值以避免NPE。Java提供了使用弱引用的集合,例如,WeakHashMap类将键(而非值)存储为弱引用。如果键是GC,则该值也会自动从地图中删除。

由于弱引用也是对象,因此我们需要一种清理它们的方法(当它们所引用的对象经过GC处理时,它们将不再有用)。如果将ReferenceQueue传递给构造函数以获取弱引用,则垃圾收集器会在完成弱化或GC之前将该弱引用附加到ReferenceQueue。您可以定期处理此队列并处理无效引用。

软参考

SoftReference就像WeakReference,但是不太可能被垃圾回收。垃圾回收器会根据内存需求酌情清除软引用。虚拟机保证在抛出OutOfMemoryError之前,将清除对所有可软访问的对象的软引用。

幻影参考

幻象引用是所有引用类型中最弱的,对它们调用get将始终返回null。在完成对象之后,但在回收分配的内存之前,对对象进行幻像引用。与在完成对象之前将其排队的弱引用或很少使用GC的幻像引用相反。

那么它们有什么用呢?构造幻像引用时,必须始终传递ReferenceQueue。这表明您可以使用幻像引用来查看对象何时进行了GC处理。

嘿,因此,如果弱引用在被认为已完成但尚未进行GC时已入队,则可以在终结器块中为该对象创建一个新的强引用,并防止该对象被GC处理。是的,可以,但是您可能不应该这样做。为检查这种情况,除非每个对象仅通过幻像引用可访问,否则GC周期将至少发生两次。这就是为什么即使内存中包含大量垃圾也可能耗尽堆的原因。幻像引用可以防止这种情况。

您可以在我的Java参考文献类型(强,软,弱,幻影)中阅读更多内容。