java.lang.ref.WeakReference和java.lang.ref.SoftReference有什么区别?
当前回答
唯一真正的区别
根据文档,松散的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.
其他回答
在Java中;从强到弱依次为:强、软、弱、幻
强引用是一种普通引用,用于保护被引用的对象不被GC收集。即从不收集垃圾。
软引用可以被垃圾回收器收集,但可能直到需要它的内存时才会被收集。即在OutOfMemoryError之前进行垃圾收集。
弱引用是指不保护被引用对象不被GC收集的引用。即,当没有强或软引用时,垃圾收集。
幻影引用是在对象完成后,但在已分配的内存被回收之前,对对象的幻影引用。
源
类比:假设JVM是一个王国,对象是王国的国王,GC是王国的攻击者,试图杀死国王(对象)。
当国王强大时,GC不能杀死他。 当国王是软的,GC攻击他,但国王统治王国的保护,直到资源可用。 当国王虚弱时,GC攻击他,但在没有保护的情况下统治王国。 当国王是幻影时,GC已经杀死了他,但国王可以通过他的灵魂获得。
弱引用 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.
为了给出一个动态内存使用方面,我做了一个实验,在重物的重负载下,将强、软、弱和幻影引用保留到程序结束。然后监控堆使用和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.
你可以在这里获得更多关于这个实验的深度图表、统计数据和观察结果。
这篇文章对于理解强引用、软引用、弱引用和幻影引用非常有帮助。
总结一下,
如果对一个对象只有弱引用(没有强引用),那么该对象将在下一个GC循环中被GC回收。
如果对对象只有软引用(没有强引用),那么只有当JVM内存耗尽时,GC才会回收该对象。
所以你可以说,强引用具有强大的功能(GC永远不会收集)。
软引用比弱引用更强大(因为它们可以逃避GC循环,直到JVM耗尽内存)
弱引用甚至不如软引用强大(因为它们不能逃避任何GC循环,如果对象没有其他强引用,就会被回收)。
餐厅的类比
服务员- GC 堆中的对象 餐厅区域/空间-堆空间 新客户-在餐厅想要桌子的新对象
现在,如果您是一个强客户(类似于强引用),那么即使餐厅里来了一个新客户或发生了其他事情,您也不会离开您的表(堆上的内存区域)。服务员没有权利告诉你(甚至要求你)离开餐厅。
如果你是一个软顾客(类似于软参考),那么如果餐厅来了一个新顾客,服务员不会让你离开桌子,除非没有其他空桌子来容纳新顾客。(换句话说,只有当一个新顾客进来,并且没有其他的桌子给这个新顾客时,服务员才会叫你离开桌子)
如果你是一个弱顾客(类似于弱参考),那么服务员可以根据他的意愿(在任何时候)要求你离开餐厅:P
软引用和弱引用之间唯一真正的区别是
垃圾收集器使用算法来决定是否 回收软可达对象,但总是回收弱可达对象 可访问的对象。
推荐文章
- 如果我同步了同一个类上的两个方法,它们能同时运行吗?
- 如何减去X天从一个日期对象在Java?
- Java标识符中的“连接字符”是什么?
- 一对多、多对一、多对多的区别?
- 从枚举中选择一个随机值?
- 如何从URL获取参数与JSP
- 如何在Eclipse中生成Javadoc注释?
- 找到java类从哪里加载
- 从集合中随机选取一个元素
- 为什么x == (x = y)和(x = y) == x不一样?
- 什么Java 8流。收集等价物可在标准Kotlin库?
- 等待未来的名单
- 如何检查JSON键是否存在?
- 为什么MongoDB Java驱动在条件中使用随机数生成器?
- 即使从未抛出异常,使用try-catch块的代价是否昂贵?