有什么不同?
来自理解弱参考,由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称为对象.即从不垃圾收集.
一个软引用是符合回收的垃圾收集器,但可能不会被收集到需要它的内存中,直到.即垃圾收集之前OutOfMemoryError
.
一个弱引用是不被GC保护引用的对象从集合的引用.即垃圾收集时没有强或软的参考.
一虚引用是它已经敲定后,一个对象的引用phantomly引用,但其分配的内存已经被回收之前.
资源
打个比方:假设JVM是一个王国,对象是王国的王者,GC是试图杀死国王(对象)的王国的攻击者.
当King 强者时,GC无法杀死他.
当金是软的时候,GC会攻击他,但是King会保护王国,直到有资源可用.
当金是弱者时,GC会攻击他,但在没有保护的情况下统治王国.
当国王是幻影时,GC已经杀死了他,但国王可以通过他的灵魂获得.
弱参考 http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ref/WeakReference.html
原理: weak reference
与垃圾收集有关.通常,具有一个或多个的对象reference
将不符合垃圾收集的条件.
如果是,上述原则不适用weak reference
.如果一个对象只有弱引用其他对象,那么它就可以进行垃圾回收了.
让我们看下面的例子:我们有一个Map
对象,其中Key引用一个对象.
import java.util.HashMap; public class Test { public static void main(String args[]) { HashMapaMap = new HashMap (); Employee emp = new Employee("Vinoth"); EmployeeVal val = new EmployeeVal("Programmer"); aMap.put(emp, val); emp = null; System.gc(); System.out.println("Size of Map" + aMap.size()); } }
现在,在我们制定的计划执行期间emp = null
.在Map
保持关键是没有意义在这里,因为它是null
.在上述情况下,对象不是垃圾回收.
WeakHashMap中
WeakHashMap
是一个在key-to-value mappings
不再可能从中检索entries()时将删除它的地方Map
.
让我用WeakHashMap显示上面的例子
import java.util.WeakHashMap; public class Test { public static void main(String args[]) { WeakHashMapaMap = new WeakHashMap (); Employee emp = new Employee("Vinoth"); EmployeeVal val = new EmployeeVal("Programmer"); aMap.put(emp, val); emp = null; System.gc(); int count = 0; while (0 != aMap.size()) { ++count; System.gc(); } System.out.println("Took " + count + " calls to System.gc() to result in weakHashMap size of : " + aMap.size()); } }
输出:注意到20 calls to System.gc()
导致aMap size
的:0.
WeakHashMap
只有对键的弱引用,而不像其他Map
类那样强引用.有些情况下,尽管您已经使用了强烈引用的值或键,但您必须注意这些情况WeakHashMap
.通过将对象包装在WeakReference中可以避免这种情况.
import java.lang.ref.WeakReference; import java.util.HashMap; public class Test { public static void main(String args[]) { HashMapmap = new HashMap (); WeakReference > aMap = new WeakReference >( map); map = null; while (null != aMap.get()) { aMap.get().put(new Employee("Vinoth"), new EmployeeVal("Programmer")); System.out.println("Size of aMap " + aMap.get().size()); System.gc(); } System.out.println("Its garbage collected"); } }
软参考.
Soft Reference
弱参考稍微强一点.软引用允许垃圾收集,但只有在没有其他选项时才请求垃圾收集器清除它.
垃圾收集器不会像弱可达对象一样积极地收集可轻松访问的对象 - 而是只收集可轻松访问的对象(如果它真的"需要"内存).软引用是对垃圾收集器说的一种方式,"只要内存不是太紧,我就想保留这个对象.但是如果内存变得非常紧张,请继续收集它,我将处理接着就,随即." 垃圾收集器需要在它可以抛出之前清除所有软引用OutOfMemoryError
.
软参考和弱参考之间唯一真正的区别是
垃圾收集器使用算法来决定是否回收可轻松访问的对象,但始终回收弱可达对象.
SoftReference
专为缓存而设计.当发现WeakReference
引用其他无法访问的对象时,它将立即被清除.SoftReference
可以保留原样.通常,存在一些与空闲存储量和最后用于确定是否应该被清除的时间有关的算法.当前的Sun算法是清除引用,如果它在Java堆上没有可用内存的数秒内被使用(可配置,服务器HotSpot检查最大可能堆的设置-Xmx
).SoftReference
s将在OutOfMemoryError
抛出之前被清除,除非另有可达.
此文章可以超有助于了解强,软,弱,虚引用。
为了给您一个总结,
如果您仅对对象具有弱引用(而没有强引用),则该对象将在下一个GC周期被GC回收。
如果您仅具有对对象的软引用(没有强引用),则仅当JVM内存不足时,GC才会回收该对象。
因此,您可以说强引用具有最终的功能(GC永远无法收集)
软引用比弱引用强大(因为它们可以逃避GC周期,直到JVM内存不足)
弱引用甚至没有软引用强大(因为它们不能排除任何GC周期,如果对象没有其他强引用,则将被回收)。
餐厅类比
服务员-GC
您-堆中的对象
餐厅面积/空间-堆空间
新客户-在餐厅要桌子的新对象
现在,如果您是一个强大的客户(类似于强大的参考客户),那么即使有新客户进来餐厅或发生的事情,您也永远不会离开桌子(堆上的内存区域)。服务员无权告诉您(甚至要求您)离开餐厅。
如果您是一位软顾客(类似于软顾客),那么如果有新顾客进来,餐厅的服务员将不会要求您离开桌子,除非没有其他空桌子来容纳新顾客。(换句话说,服务员只会在有新客户进入并且没有其他可供该新客户使用的桌子时才要求您离开桌子)
如果您是弱顾客(类似于弱顾客),那么服务员可以(在任何时间)要求您离开餐厅:P
根据文档,必须通过正在运行的GC清除松散的WeakReferences .
根据doc,在抛出OOM之前必须清除松散的SoftReferences .
这是唯一真正的区别.其他一切都不是合同的一部分.(我假设最新的文档是合同的.)
SoftReferences非常有用.内存敏感的缓存使用SoftReferences,而不是WeakReferences.
weak_ref.get()
.如果是这样null
,你就会知道在这段时间内,GC会运行.
至于错误使用WeakReference,列表是无穷无尽的:
实现优先级2软引用的糟糕黑客,这样您就不必编写一个,但它不能按预期工作,因为即使有空闲内存,每次 GC运行时都会清除缓存.有关phails,请参阅 /sf/ask/17360801/.(此外,如果您需要超过2个级别的缓存优先级呢?您仍然需要一个真正的库.)
将数据与现有类的对象关联的糟糕黑客,但是当您的GC决定在创建弱引用后休息时,它会创建内存泄漏(OutOfMemoryError).此外,它超出了丑陋:更好的方法是使用元组.
将数据与现有类的对象相关联的糟糕黑客,其中类具有使其自身不可子类化的神经,并且在您需要调用的现有函数代码中使用.在这种情况下,正确的解决方案是编辑类并使其成为子类,或编辑函数并使其采用接口而不是类,或使用替代函数.