Java中的SoftReference和WeakReference有什么区别?

问题

Java中的SoftReference和WeakReference有什么区别?它们有什么不同?


#1 热门回答(806 赞)

来自Understanding Weak References,作者:Ethan Nicholas:

弱引用弱引用,简单地说,是一个不足以强制对象保留在内存中的引用。弱引用允许你利用垃圾收集器为你确定可达性的能力,因此你不必自己执行此操作。你创建一个像这样的弱引用:WeakReference weakWidget = new WeakReference(widget);
 然后在代码的其他地方你可以使用weakWidget.get()来获取实际的Widget对象。当然,弱引用不足以阻止垃圾收集,因此你可能会发现(如果没有对小部件的强引用)weakWidget.get()突然开始返回null。 ...软引用软引用与弱引用完全相同,只是它不太愿意丢弃它引用的对象。一个只能弱到达的对象(对它的最强引用是WeakReferences)将在下一个垃圾收集周期被丢弃,但是一个可以轻松到达的对象通常会暂停一段时间。 SoftReferences的行为不需要与WeakReferences有任何不同,但实际上,只要内存供应充足,就可以保留软可访问对象。这使得它们成为缓存的良好基础,例如上面描述的图像缓存,因为你可以让垃圾收集器担心对象的可达性(永远不会从缓存中移除强可达对象)以及它有多糟糕需要他们消耗的记忆。

AndPeter Kessler在评论中添加:

Sun JRE确实以不同于WeakReferences的方式处理SoftReferences。如果可用内存没有压力,我们会尝试保持SoftReference引用的对象。一个细节:“-client”和“-server”JRE的策略是不同的:-client JRE试图通过清除SoftReferences而不是扩展堆来保持你的足迹小,而-server JRE尝试保留你的通过优先扩展堆(如果可能)而不是清除SoftReferences来提高性能。一种尺寸并不适合所有人。


#2 热门回答(183 赞)

急切地收集弱引用。如果GC发现某个对象是弱可达的(只能通过弱引用访问),它将立即清除对该对象的弱引用。因此,它们有助于保持对程序也保留(强烈引用)“关联信息”的对象的引用,例如关于类的缓存反射信息,或对象的包装器等。任何使得在它与之关联的对象之后保持不变是GC-ed。当弱引用被清除时,它会在代码轮询某个地方的引用队列中排队,并且它也会丢弃关联的对象。也就是说,你保留有关对象的额外信息,但一旦它引用的对象消失,就不需要该信息。实际上,在某些情况下,你甚至可以继承WeakReference,并在WeakReference子类的字段中保留有关该对象的相关额外信息。 WeakReference的另一个典型用法是与Maps一起保存规范实例。

另一方面,SoftReferences适用于缓存外部可再生资源,因为GC通常会延迟清除它们。虽然在抛出OutOfMemoryError之前所有SoftReferences都会被清除,但是理论上它们不会导致OOME [*]。

典型的用例示例是从文件中保留已解析形式的内容。你将实现一个系统,你可以在其中加载文件,解析文件,并将SoftReference保留在已解析表示的根对象中。下次需要该文件时,你将尝试通过SoftReference检索它。如果你可以检索它,你可以节省自己的另一个加载/解析,如果GC在此期间清除它,你重新加载它。这样,你可以利用可用内存进行性能优化,但不要冒OOME风险。

现在为[*]。保持SoftReference本身不会导致OOME。另一方面,如果你错误地将SoftReference用于任务,则应使用WeakReference(即,你以某种方式强烈引用与Object关联的信息,并在Reference对象被清除时丢弃它),你可以运行到OOME中轮询ReferenceQueue并丢弃关联对象的代码可能不会及时运行。

因此,决定取决于使用情况 - 如果你正在缓存构造成本高昂的信息,但仍然可以从其他数据重建,请使用软引用 - 如果你要保留对某些数据的规范实例的引用,或者你希望引用一个没有“拥有”它的对象(从而防止它被GC化),使用弱引用。


#3 热门回答(97 赞)

在Java中;从最强到最弱的顺序,有:强,软,弱和幻影

A强引用是一个普通引用,它通过GC保护引用对象不被集合。即从不垃圾收集。

A软参考符合垃圾收集器的收集条件,但在需要内存之前可能不会收集。即垃圾收集在'OutOfMemoryError`之前。

A弱引用是一个引用,它不保护引用的对象不被GC收集。即没有强力或软质参考时垃圾收集。

A幻像引用是一个对象的引用,它在完成后被引用,但在其已分配的内存被回收之前被引用。

Source

**类比:**假设JVM是一个王国,物体是王国的王者,GC是试图杀死国王(物体)的王国的攻击者。

  • 当King强者时,GC无法杀死他。
  • 当King为Soft时,GC会攻击他,但King会保护王国,直到有资源可用。
  • 当King为弱者时,GC会攻击他,但在没有保护的情况下统治王国。
  • 当国王是幻影时,GC已经杀死了他,但国王可以通过他的灵魂获得。