0%

Java的强、弱、软、虚引用

从JDK 1.2版本开始,对象的引用被划分为4种级别,从而使程序能更加灵活地控制对象的生命周期。这4种级别由高到低依次为:强引用、软引用、弱引用和虚引用。

主要是用于给GC回收而使用,软引用和弱引用多用于处理缓存方面,如ThreadLocal
持有的map对象就是属于弱引用,在GC的时候会自动回收以免出现OOM的异常。

四种类型

强引用:无论啥情况下,只要持有就不会被回收
软引用:内存不足时引用对象可被虚拟机回收,但是system.gc对其无效
弱引用:同软引用,在对象没有其他引用的情况下,调用system.gc对象可被虚拟机回收
虚引用:就只是一个标识,对象的生命周期不受期影响

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
public class TestReference {
private Integer _10M = 1024 * 10;
private Integer _1M = 1024;

/**
* 强引用的资源回收情况
* 因为不会被GC,最终会引发OOM
* ![](http://pic.ztianzeng.com/20190918151513.png)
*/
public void testStrongReference() {
ArrayList<byte[]> strongList = new ArrayList<>();
try {
while (true) {
strongList.add(new byte[_1M]);
Thread.sleep(2);
}
} catch (OutOfMemoryError | InterruptedException e) {
e.printStackTrace();
}
}

/**
* 弱引用
* 这种永远不会内存溢出,因为一旦发现了只具有弱引用的对象,GC时不管当前内存空间足够与否,都会回收它的内存
* ![](http://pic.ztianzeng.com/20190918141112.png)
*/
public void testWeakReference() {
ArrayList<WeakReference<byte[]>> strongList = new ArrayList<>();
try {
while (true) {
strongList.add(new WeakReference<>(new byte[_10M]));
}
} catch (OutOfMemoryError e) {
e.printStackTrace();
}
}

/**
* 软引用,内存不足时回收
* 这种永远不会内存溢出,因为一旦发现了只具有弱引用的对象,只有在当前内存空间不够了,才会回收它的内存
* ![](http://pic.ztianzeng.com/20190918161245.png)
*/
public void testSoftReference() {
ArrayList<SoftReference<byte[]>> strongList = new ArrayList<>();
try {
while (true) {
strongList.add(new SoftReference<>(new byte[_10M]));
}
} catch (OutOfMemoryError e) {
e.printStackTrace();
}
}

/**
* 虚引用
* 虚引用必须和引用队列联合使用。
* 当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。
*/
public void testPhantomReference() {
ArrayList<PhantomReference<byte[]>> strongList = new ArrayList<>();
ReferenceQueue queue = new ReferenceQueue();
System.out.println(queue.poll() == null);
try {
while (true) {
strongList.add(new PhantomReference<>(new byte[_10M], queue));
}
} catch (OutOfMemoryError e) {
e.printStackTrace();
}
System.out.println(queue.poll() == null);
}

public static void main(String[] args) {
TestReference t = new TestReference();
t.testPhantomReference();
}
}