java.lang.ref.WeakReference和java.lang.ref.SoftReference有什么区别?


当前回答

软引用和弱引用之间唯一真正的区别是

垃圾收集器使用算法来决定是否 回收软可达对象,但总是回收弱可达对象 可访问的对象。

其他回答

软引用和弱引用之间唯一真正的区别是

垃圾收集器使用算法来决定是否 回收软可达对象,但总是回收弱可达对象 可访问的对象。

Java中的六种对象可达性状态:

Strongly reachable objects - GC will not collect (reclaim the memory occupied by) this kind of object. These are reachable via a root node or another strongly reachable object (i.e. via local variables, class variables, instance variables, etc.) Softly reachable objects - GC may attempt to collect this kind of object depending on memory contention. These are reachable from the root via one or more soft reference objects Weakly reachable objects - GC must collect this kind of object. These are reachable from the root via one or more weak reference objects Resurrect-able objects - GC is already in the process of collecting these objects. But they may go back to one of the states - Strong/Soft/Weak by the execution of some finalizer Phantomly reachable object - GC is already in the process of collecting these objects and has determined to not be resurrect-able by any finalizer (if it declares a finalize() method itself, then its finalizer will have been run). These are reachable from the root via one or more phantom reference objects Unreachable object - An object is neither strongly, softly, weakly, nor phantom reachable, and is not resurrectable. These objects are ready for reclamation

欲了解更多详细信息:https://www.artima.com/insidejvm/ed2/gc16.html«崩溃

这篇文章对于理解强引用、软引用、弱引用和幻影引用非常有帮助。


总结一下,

如果对一个对象只有弱引用(没有强引用),那么该对象将在下一个GC循环中被GC回收。

如果对对象只有软引用(没有强引用),那么只有当JVM内存耗尽时,GC才会回收该对象。


所以你可以说,强引用具有强大的功能(GC永远不会收集)。

软引用比弱引用更强大(因为它们可以逃避GC循环,直到JVM耗尽内存)

弱引用甚至不如软引用强大(因为它们不能逃避任何GC循环,如果对象没有其他强引用,就会被回收)。


餐厅的类比

服务员- GC 堆中的对象 餐厅区域/空间-堆空间 新客户-在餐厅想要桌子的新对象

现在,如果您是一个强客户(类似于强引用),那么即使餐厅里来了一个新客户或发生了其他事情,您也不会离开您的表(堆上的内存区域)。服务员没有权利告诉你(甚至要求你)离开餐厅。

如果你是一个软顾客(类似于软参考),那么如果餐厅来了一个新顾客,服务员不会让你离开桌子,除非没有其他空桌子来容纳新顾客。(换句话说,只有当一个新顾客进来,并且没有其他的桌子给这个新顾客时,服务员才会叫你离开桌子)

如果你是一个弱顾客(类似于弱参考),那么服务员可以根据他的意愿(在任何时候)要求你离开餐厅:P

WeakReference:只弱引用的对象将在每个GC周期(minor或full)收集。

SoftReference:当只被软引用的对象被收集时,取决于:

-XX:SoftRefLRUPolicyMSPerMB=N标志(默认值是1000,也就是1秒) 堆中的空闲内存量。 例子: 堆有10MB的空闲空间(在完全GC之后); - xx: SoftRefLRUPolicyMSPerMB = 1000 如果只被SoftReference引用的对象上次被访问的时间大于10秒,则该对象将被收集。

唯一真正的区别

根据文档,松散的weakreference必须由正在运行的GC清除。

根据文档,在抛出OOM之前必须清除松散的softreference。

这是唯一真正的区别。其他的都不是合同的一部分。(我假设最新的文件是合同文件。)

软引用很有用。内存敏感的缓存使用软引用,而不是弱引用。 WeakReference的唯一正确用法是观察GC运行。为此,您可以创建一个新的WeakReference,其对象立即超出作用域,然后尝试从weak_ref.get()中获取null。当它为空时,您可以了解到在此期间GC运行了。

关于WeakReference的错误使用,列表是无限的:

a lousy hack to implement priority-2 softreference such that you don't have to write one, yet it doesn't work as expected because the cache would be cleared on every GC run, even when there is spare memory. See https://stackoverflow.com/a/3243242/632951 for phails. (Besides, what if you need more than 2 levels of cache priority? You'd still gotta need a real library for it.) a lousy hack to associate data with an object of an existing class, yet it creates a memory leak (OutOfMemoryError) when your GC decides to take a break after your weakreferences are created. Besides, it's beyond ugly: A better approach is to use tuples. a lousy hack to associate data with an object of an existing class, where the class has the nerve to make itself non-subclassable, and is used in an existing function code which you need to call. In such a case, the proper solution is to either edit the class and make it subclassable, or edit the function and make it take an interface instead of a class, or use an alternative function.