What's the difference between SoftReference and WeakReference in Java?
根据Ethan Nicholas的《理解弱参考文献》:
Weak references
A weak reference, simply put, is a
reference that isn't strong enough to
force an object to remain in memory.
Weak references allow you to leverage
the garbage collector's ability to
determine reachability for you, so you
don't have to do it yourself. You
create a weak reference like this:
1and then
elsewhere in the code you can use
weakWidget.get() to get the actual
Widget object. Of course the weak
reference isn't strong enough to
prevent garbage collection, so you may
find (if there are no strong
references to the widget) that
weakWidget.get() suddenly starts
returningnull ....
Soft references
A soft reference is exactly like a
weak reference, except that it is less
eager to throw away the object to
which it refers. An object which is
only weakly reachable (the strongest
references to it areWeakReferences )
will be discarded at the next garbage
collection cycle, but an object which
is softly reachable will generally
stick around for a while.
SoftReferences aren't required to
behave any differently than
WeakReferences , but in practice softly
reachable objects are generally
retained as long as memory is in
plentiful supply. This makes them an
excellent foundation for a cache, such
as the image cache described above,
since you can let the garbage
collector worry about both how
reachable the objects are (a strongly
reachable object will never be removed
from the cache) and how badly it needs
the memory they are consuming.
彼得·凯斯勒在评论中补充道:
The Sun JRE does treat SoftReferences differently from WeakReferences. We attempt to hold on to object referenced by a SoftReference if there isn't pressure on the available memory. One detail: the policy for the"-client" and"-server" JRE's are different: the -client JRE tries to keep your footprint small by preferring to clear SoftReferences rather than expand the heap, whereas the -server JRE tries to keep your performance high by preferring to expand the heap (if possible) rather than clear SoftReferences. One size does not fit all.
薄弱的参考资料被热切地收集起来。如果GC发现一个对象弱可到达(仅通过弱引用可到达),它将清除立即弱引用该对象。因此,它们对保留对程序也为其保留的对象的引用(强引用)"关联信息"一些,如缓存的关于类或对象包装器等的反射信息。在与之关联的对象之后保留没有意义的任何内容当弱引用被清除时,它将在您的代码在某个地方轮询的引用队列,它将丢弃关联的对象也一样。也就是说,您保留有关对象,但一旦对象引用该信息,就不需要该信息。走开。实际上,在某些情况下,您甚至可以子类Weakreference并保留与对象相关的额外信息在weakreference子类中。另一个典型的用途是weakreference与保存规范实例的映射结合在一起。
另一方面,软引用有利于缓存外部可重新创建的资源。因为GC通常会延迟清除它们。尽管这一切都是有保证的SoftReferences将在抛出OutOfMemoryError之前被清除,因此它们理论上不会引起OOME[*]。
典型的用例示例是从文件。您将实现一个系统,在该系统中您将加载一个文件,对其进行分析,并保留对解析表示的根对象的软引用。下次您需要这个文件,您将尝试通过SoftReference检索它。如果您可以检索它,您省去了另一个加载/解析,如果GC同时清除它,重新加载它。这样,你就可以免费使用内存用于性能优化,但不要冒险使用OOME。
现在为[*]。保持一个软引用本身不能引起OOME。如果另一方面,您错误地将软引用用于任务,weakreference是指要使用(即,您以某种方式保留与对象相关联的信息强引用,并在引用对象清除),您可以将OOME作为轮询引用队列的代码运行。丢弃关联的对象可能会在时尚。
因此,决定取决于使用情况-如果您正在缓存构建成本很高的信息,但是尽管如此,还是可以从其他数据中重建,使用软引用-如果您保留对某些数据的规范实例的引用,或者您希望引用一个对象而不"拥有"它(因此防止它成为gc'd),使用弱引用。
在Java中,从一阶strongest weakest有:强,弱,软,和幻影
一个强大的参考是一个正常的参考对象,它是由被从收集的GC。没有垃圾collects IU。
a软使用的参考是由垃圾收集器的收集,但可能不会太小,直到它是需要记忆的。在
这是一个参考参考A弱引用的对象不正确A从收集的GC。垃圾collects IU当NO强参或软。
A是一个虚拟参考参考引用的对象是phantomly后它已finalized,但在其分配的内存已被再生。
源
JVM的类比:假设a是一个对象是一个王国,国王是一个王国,和GC attacker谁试图杀死的王国国王(对象)。
- 当国王是不强,GC CAN杀死他。
- 当国王是软,但GC攻击他。直到金规则与保护资源是可用的。
- 当国王的GC是弱,但规则没有攻击他国的保护。
- 当国王已经被杀的GC是幽灵,他通过他的灵魂,但国王是可用的。
弱引用docs.oracle.com http:/ / / / /文档/ JavaSE 1.5.0 Java API参考/ / /时间/ weakreference.html
原则是:
让我们看下面的例子:我们有一个关键是在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import java.util.HashMap; public class Test { public static void main(String args[]) { HashMap<Employee, EmployeeVal> aMap = new HashMap<Employee, EmployeeVal>(); 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()); } } |
现在,在我们的执行程序
weakhashmap
这是一个在
让我展示一个例子weakhashmap上面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | import java.util.WeakHashMap; public class Test { public static void main(String args[]) { WeakHashMap<Employee, EmployeeVal> aMap = new WeakHashMap<Employee, EmployeeVal>(); 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()); } } |
输出:一个是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import java.lang.ref.WeakReference; import java.util.HashMap; public class Test { public static void main(String args[]) { HashMap<Employee, EmployeeVal> map = new HashMap<Employee, EmployeeVal>(); WeakReference<HashMap<Employee, EmployeeVal>> aMap = new WeakReference<HashMap<Employee, EmployeeVal>>( 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"); } } |
软引用。
在垃圾收集器收集的对象,不aggressively轻轻地到达和到达的方式它是一弱——它只会collects轻轻可达对象,如果它真的"需要"的记忆。软引用是一个垃圾收集器的方式说,"只要记忆不是太紧张,我想把这个对象周围。但如果内存变得很紧,去收集它,那我就交易。"垃圾收集器清除所有引用所需的软到在它可以
软引用和弱引用之间唯一的区别是
the garbage collector uses algorithms to decide whether or not to
reclaim a softly reachable object, but always reclaims a weakly
reachable object.
唯一真正的区别
根据文档,松散的weakreference必须由正在运行的GC清除。
根据文档,在抛出OOM之前,必须清除松散的软引用。
这是唯一真正的区别。其他一切都不是合同的一部分。(我假设最新的文件是合同规定的。)
软引用是有用的。内存敏感的缓存使用软引用,而不是weakreferences。Weakreference的唯一正确使用是观察GC运行。您可以通过创建一个新的weakreference来实现这一点,该weakreference的对象立即超出范围,然后尝试从
对于weakreference的错误使用,列表是无止境的:
实现priority-2软引用的一个糟糕的黑客程序,这样你就不必写一个,但它并没有按预期工作,因为缓存在每次GC运行时都会被清除,即使有空闲的内存。请参阅https://stackoverflow.com/a/3243242/632951了解PHAILS。(此外,如果您需要两个以上级别的缓存优先级呢?你还需要一个真正的图书馆。)
将数据与现有类的对象相关联是一个糟糕的方法,但是当GC决定在创建weakreferences之后稍作休息时,它会导致内存泄漏(outofmemoryerror)。除此之外,它是非常丑陋的:更好的方法是使用元组。
将数据与现有类的对象关联起来的一种糟糕的方法,在这种方法中,类具有使自己不可子类化的勇气,并用于需要调用的现有函数代码中。在这种情况下,正确的解决方案是要么编辑类并使其成为子类,要么编辑函数并使其采用接口而不是类,或者使用可选函数。
本文对理解强、软、弱和幻象的参考文献有很大帮助。
给你一个总结,
如果只有对某个对象的弱引用(没有强引用),那么该对象将在下一个GC循环中由GC回收。
如果只有对对象的软引用(没有强引用),那么只有当JVM耗尽内存时,GC才会回收该对象。
所以你可以说,强引用具有终极的能力(GC永远无法收集到)。
软引用比弱引用强大(因为它们可以在JVM耗尽内存之前退出GC循环)
弱引用甚至不如软引用强大(因为它们不能排除任何GC循环,如果对象没有其他强引用,则将被回收)。
餐厅类比
- 服务员-气相色谱法
- 你-堆中的对象
- 餐厅区域/空间-堆空间
- 新客户-餐厅需要桌子的新对象
现在,如果你是一个强大的客户(类似于强大的推荐人),那么即使一个新客户来了餐厅或发生了什么,你永远不会离开你的桌子(记忆区堆)。服务员无权告诉你(甚至要求你)离开餐厅。
如果你是一个软客户(类似于软参考),那么如果一个新客户来到餐厅,服务员不会要求你离开桌子,除非没有其他空桌子来容纳新客户。(换言之,只有当新客户进来时,服务生才会要求您离开桌子,而这个新客户没有其他的桌子了)
如果你是一个软弱的顾客(类似于软弱的推荐人),那么服务员可以(在任何时候)随意要求你离开餐馆:p
Java中的六类对象可达性状态
更多详情:https://www.artima.com/insidejvm/ed2/gc16.html?崩溃
weakreference:在每个GC循环(次要或完整)中收集仅弱引用的对象。
软引用:收集仅软引用的对象时取决于:
-xx:softreflupolicymspemb=n标志(默认值为1000,即1秒)
堆中的可用内存量。
例子:
- 堆有10MB的可用空间(在完全GC之后);
- -xx:软反射系数mspermb=1000
如果上次访问对象的时间大于10秒,则只由SoftReference引用的对象将被收集。
应该知道,弱引用对象只有在只有弱引用时才会被收集。如果它有这么多强引用,那么不管它有多少弱引用,都不会收集到它。