java.lang.ref.WeakReference和java.lang.ref.SoftReference有什么区别?
当前回答
弱引用 http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ref/WeakReference.html
原理:弱引用与垃圾回收相关。通常,具有一个或多个引用的对象将不符合垃圾收集的条件。 上述原则在弱参考时不适用。如果一个对象对其他对象只有弱引用,那么它就可以进行垃圾收集了。
让我们看看下面的例子:我们有一个Map with Objects,其中Key是引用一个对象。
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());
}
}
现在,在程序执行期间,我们使emp = null。持有键的Map在这里没有意义,因为它是空的。在上述情况下,对象不会被垃圾收集。
WeakHashMap
在WeakHashMap中,当不再可能从Map中检索条目时,条目(键到值的映射)将被删除。
让我用WeakHashMap展示上面的例子
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());
}
}
输出:对System.gc()进行了20次调用,导致高德地图大小为:0。
WeakHashMap只有对键的弱引用,没有像其他Map类那样的强引用。虽然使用了WeakHashMap,但在某些情况下,当值或键被强引用时,您必须小心。这可以通过将对象包装在WeakReference中来避免。
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");
}
}
软引用。
软引用比弱引用强一些。软引用允许垃圾回收,但只有在没有其他选择时才请求垃圾回收器清除它。
The garbage collector does not aggressively collect softly reachable objects the way it does with weakly reachable ones -- instead it only collects softly reachable objects if it really "needs" the memory. Soft references are a way of saying to the garbage collector, "As long as memory isn't too tight, I'd like to keep this object around. But if memory gets really tight, go ahead and collect it and I'll deal with that." The garbage collector is required to clear all soft references before it can throw OutOfMemoryError.
其他回答
唯一真正的区别
根据文档,松散的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.
摘自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: WeakReference weakWidget = new WeakReference(widget); and 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 returning null. ... 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 are WeakReferences) 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.
Peter Kessler补充道:
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行为。这些指标可能因情况而异,但肯定能提供高层次的理解。以下是调查结果。
重负载下的堆和GC行为
Strong/Hard Reference - As program continued, JVM couldn't collect retained strong referenced object. Eventually ended up in "java.lang.OutOfMemoryError: Java heap space" Soft Reference - As program continued, heap usage kept growing, but OLD gen GC happened hen it was nearing max heap. GC started bit later in time after starting program. Weak Reference - As program started, objects started finalizing & getting collected almost immediately. Mostly objects got collected in young generation garbage collection. Phantom Reference - Similar to weak reference, phantom referenced objects also started getting finalized & garbage collected immediately. There were no old generation GC & all objects were getting collected in young generation garbage collection itself.
你可以在这里获得更多关于这个实验的深度图表、统计数据和观察结果。
SoftReference is designed for caches. When it is found that a WeakReference references an otherwise unreachable object, then it will get cleared immediately. SoftReference may be left as is. Typically there is some algorithm relating to the amount of free memory and the time last used to determine whether it should be cleared. The current Sun algorithm is to clear the reference if it has not been used in as many seconds as there are megabytes of memory free on the Java heap (configurable, server HotSpot checks against maximum possible heap as set by -Xmx). SoftReferences will be cleared before OutOfMemoryError is thrown, unless otherwise reachable.
WeakReference:只弱引用的对象将在每个GC周期(minor或full)收集。
SoftReference:当只被软引用的对象被收集时,取决于:
-XX:SoftRefLRUPolicyMSPerMB=N标志(默认值是1000,也就是1秒) 堆中的空闲内存量。 例子: 堆有10MB的空闲空间(在完全GC之后); - xx: SoftRefLRUPolicyMSPerMB = 1000 如果只被SoftReference引用的对象上次被访问的时间大于10秒,则该对象将被收集。
推荐文章
- CountDownLatch是如何在Java多线程中使用的?
- 如果我同步了同一个类上的两个方法,它们能同时运行吗?
- 如何减去X天从一个日期对象在Java?
- Java标识符中的“连接字符”是什么?
- 一对多、多对一、多对多的区别?
- 从枚举中选择一个随机值?
- 如何从URL获取参数与JSP
- 如何在Eclipse中生成Javadoc注释?
- 找到java类从哪里加载
- 从集合中随机选取一个元素
- 为什么x == (x = y)和(x = y) == x不一样?
- 什么Java 8流。收集等价物可在标准Kotlin库?
- 等待未来的名单
- 如何检查JSON键是否存在?
- 为什么MongoDB Java驱动在条件中使用随机数生成器?