协慌网

登录 贡献 社区

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

答案

来自理解弱参考 ,由 Ethan Nicholas 撰写:

弱参考

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

WeakReference weakWidget = new WeakReference(widget);

然后在代码中的其他地方你可以使用weakWidget.get()来获取实际的Widget对象。当然,弱引用不足以阻止垃圾收集,因此您可能会发现(如果没有对小部件的强引用) weakWidget.get()突然开始返回null

...

软参考

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

SoftReferences 不需要WeakReferences任何不同的行为,但实际上,只要内存供应充足,就可以保留软可访问对象。这使得它们成为缓存的良好基础,例如上面描述的图像缓存,因为您可以让垃圾收集器担心对象的可达性( 永远不会从缓存中移除强可达对象)以及它有多糟糕需要他们消耗的记忆。

Peter Kessler 在评论中补充道:

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

急切地收集弱引用。如果 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 化),使用弱引用。

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

强引用是一种常规引用,用于保护引用的对象不受 GC 的收集。即从不垃圾收集。

Soft 引用有资格由垃圾收集器收集,但在需要内存之前可能不会收集。即垃圾在OutOfMemoryError之前收集。

弱引用是不保护引用对象不受 GC 收集的引用。即垃圾收集时没有强或软的参考。

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

资源

打个比方:假设 JVM 是一个王国,对象是王国的王者,GC 是试图杀死国王(对象)的王国的攻击者。

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