关于java各种引用的思考
2017-08-31 本文已影响152人
2053d13b70b7
经常可以看到这样的文章,强引用、软引用、弱引用、虚引用到底有啥区别,大神们的回答几乎都是差不多的,软引用在内存不足时会被gc回收,弱引用只要发生gc就会被回收(强引用和虚引用就不扯了,这两个说了也没意思)。每次看完之后经常会觉得自己信心满满,也是大神了~
直到某天翻了下WeakHashMap的源码,才发现自己懂得并没有那么多。
我们通过一个示例来分析下大神们的话到底什么意思……
如果你知道下面几个示例的输出,那么完全不需要看这篇小白文~~
1、代码示例
模拟内存不足比较麻烦,所以直接WeakReference的作为例子,毕竟只要加个System.gc()就可以模拟了~
模拟一个对象
public class Demo {
String value;
public Demo(String value) {
this.value = value;
}
public String toString() {
return this.value;
}
}
1.1、测试1
public void testCase1() {
Demo demo1 = new Demo("hello world");
WeakReference<Demo> sr = new WeakReference<Demo>(demo1);
demo1 = null;
System.gc();
System.out.println(sr.get());
}
1.2 、测试2
public void testCase2() {
Demo demo1 = new Demo("hello world");
WeakReference<Demo> sr = new WeakReference<Demo>(demo1);
Demo demo2 = new Demo("hello world2");
demo2 = demo1;
demo1 = null;
System.gc();
System.out.println(sr.get());
}
1.3 、测试3
public void testCase3() {
Demo demo1 = new Demo("hello world");
WeakReference<Demo> sr = new WeakReference<Demo>(demo1);
List<Demo> lists = Lists.newArrayList();
lists.add(demo1);
demo1 = null;
System.gc();
System.out.println(sr.get());
}
1.4 、测试4
public void testCase4() {
Demo demo1 = new Demo("hello world");
WeakReference<Demo> sr = new WeakReference<Demo>(demo1);
List<WeakReference> lists = Lists.newArrayList();
lists.add(sr);
demo1 = null;
System.gc();
System.out.println(sr.get());
}
1.5、测试5
public void testCase5() {
Demo demo1 = new Demo("hello world");
WeakReference<Demo> sr = new WeakReference<Demo>(demo1);
SoftReference<Demo> sf = new SoftReference<Demo>(demo1);
demo1 = null;
System.gc();
System.out.println(sr.get());
}
每个用例输出什么呢???
下面先给出每个测试用例的输出结果:
testCase1:null
testCase2:hello world
testCase3:hello world
testCase4:null
testCase5:hello world
通俗翻译下各路大神关于WeakReference和SoftReference的总结,然后再来说明这几个例子:
WeakReference:每次gc的时候,如果一个对象A只被WeakReference直接引用,那么A就可以被回收掉;
SoftReference:每当内存不足的时候(其实和WeakReference差不多),如果一个对象A只被SoftReference或WeakReference直接引用,那么A就可以被回收掉;
注意:内存不足或者gc的时候,回收的不是reference对象本身,而是reference所引用的对象
运用这个规则,解释下上面的每个testCase:
- testCase1:WeakReference sr保持了一个对demo1实例的引用,在demo1=null后,demo1除了sr没有直接指向它的引用,所以gc后demo1对象可以被回收掉;
- testCase2:demo2保持了一个对demo1实例的强引用,所以gc后demo1实例其实还活着,sr.get()理所当然可以看到值;
- testCase3:lists对象保持了对demo1实例的强引用,分析同testCase2;
- testCase4:强引用lists引用了sr,从而lists通过sr间接引用了demo1,这种情况下也是会被回收掉的(因为回收的时候,只考虑直接引用哦~~)。典型的例子可以参考jdk源码的WeakHashMap;
- testCase5:SoftReference添加了对demo1的引用,在gc的时候,demo1上有SoftReference和WeakReference两个引用,而SoftReference规定只有在内存不足的时候才会干掉demo1,所以这个例子中demo1也活着。