Java/Java 中的强引用、软引用、弱引用、虚引用
- 强引用(Strong Reference)
- 最普遍的引用:Object obj = new Object();
- 内存不够时,即使抛出 OOM 也不会回收具有强引用的对象
- 通过将对象设置为 null,使其被回收
- 软引用(Soft Reference)
- 弱引用(Weak Reference)
- 非必须对象,比软引用更弱一些,生命周期更短
- 无论内存是否充足,GC 扫描一旦发现弱引用,便会回收
- 由于 GC 线程优先级很低,因此不一定会很快发现弱引用
- 适用于引用偶尔被使用,且不会被垃圾收集影响的对象
- 可以配合引用队列来使用
1
2String str=new String("abc");
WeakReference<String> weakReference = new WeakReference<String>(str);
- 虚引用(Phantom Reference)
- 不会决定对象的生命周期
- 虚引用就和没有任何引用一样,任何时候都有可能被垃圾回收器回收
- 主要作用是跟踪对象被垃圾回收器的活动,起到哨兵的作用
- 必须配合引用队列 ReferenceQueue 来使用。GC 在回收一个对象时,如果发现该对象具有虚引用,在回收之前会将该虚引用加入到与之关联的引用队列中,程序可以通过判断引用队列中是否已经加入虚引用来判断被引用的对象是否已经被 GC 回收
1
2
3String str=new String("abc");
ReferenceQueue queue=new ReferenceQueue();
PhantomReference reference = new PhantomReference(str,queue);
- 引用队列(ReferenceQueue)
- 无实际存储结构,存储逻辑依赖于内部节点之间的关系来表达
- 存储关联且被 GC 的软引用,弱引用以及虚引用
- 下面是一个例子:
定义一个一个普通类 1
2
3
4
5
6
7
8
9
10
11
12
13
14//创建一个普通对象的类
public class NormalObject {
public String name;
public NormalObject(String name) {
this.name = name;
}
//重写 finalize 方法
@Override
protected void finalize() throws Throwable {
System.out.println("Finalizing obj " + name);
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public class NormalObjectWeakReference extends WeakReference<NormalObject> {
public String name;
//在弱引用里面引用 NormalObject 对象
public NormalObjectWeakReference(NormalObject referent, ReferenceQueue<NormalObject> rq) {
super(referent, rq);
this.name = referent.name;
}
//重写 finalize 方法
@Override
protected void finalize() throws Throwable {
System.out.println("Finalizing NormalObjectWeakReference " + name);
}
}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
35public class ReferenceQueueTest {
private static ReferenceQueue<NormalObject> rq=new ReferenceQueue<>();
//遍历引用队列,并输出每一个弱引用的名字和实际引用的对象
private static void checkQueue(){
Reference<NormalObject> ref=null;
while ((ref= (Reference<NormalObject>) rq.poll())!=null){
if ((ref!=null)){
System.out.println("In queue: "+((NormalObjectWeakReference)ref).name);
System.out.println("reference object: "+ref.get());
}
}
}
public static void main(String[] args) {
ArrayList<WeakReference<NormalObject>> weakLists=new ArrayList<>();
//向队列里添加弱引用
for (int i = 0; i < 3; i++) {
weakLists.add(new NormalObjectWeakReference(new NormalObject("Weak "+i),rq));
System.out.println("Created weak: "+weakLists.get(i));
}
System.out.println("first time");
checkQueue();//第一次由于还没有进行 GC,所以引用队列为空,checkQueue 方法无输出
System.gc();//这里触发对象的 finalize 方法,并把弱引用添加到引用队列
try {
//这里睡眠 1 秒,让 GC 有足够时间运行完成
Thread.currentThread().sleep(1000);
}catch (Exception e){
e.printStackTrace();
}
System.out.println("second time");//第二次由于经过了 GC,所以引用队列不为空,但是弱引用所指向的对象为空
checkQueue();
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14Created weak: gc.NormalObjectWeakReference@60e53b93
Created weak: gc.NormalObjectWeakReference@5e2de80c
Created weak: gc.NormalObjectWeakReference@1d44bcfa
first time
Finalizing obj Weak 2
Finalizing obj Weak 1
Finalizing obj Weak 0
second time
In queue: Weak 2
reference object: null
In queue: Weak 1
reference object: null
In queue: Weak 0
reference object: null