参考链接:
简介
Java垃圾回收机制主要看是否有引用指向该对象。
Java对象的引用包括:强引用、弱引用、软引用、虚引用。
Java提供四种引用主要有两个目的:
- 方便通过代码控制对象的生命周期;
- 有利于JVM进行垃圾回收;
1、强引用
创建一个对象并把这个对象直接赋值给引用变量。
e.g.:
Person personA = new Person("Justin", "16");
Person personB = personA;
创建新的Person对象,personA和personB引用这个对象,这两个引用都是强引用。
强引用有引用变量指向时永远不会被垃圾回收,JVM抛出OOM错误也不会回收这种对象。
当在作用域外personA和personB都不存在,指向的对象也没有其他引用,则会被回收。
如果想中断强引用和某个对象之间的关联,可以显示地将引用赋值为null,对象失去引用会在适合的时候被JVM回收。
personA = null;
personB = null;
2、软引用(SoftReference)
如果一个对象具有软引用,当内存空间足够时,垃圾回收器不会回收它,当内存空间不足时,垃圾回收器会回收这些对象的内存。
JVM对于软可及对象的回收是由垃圾收集线程根据其特定算法按照内存需求决定的。
只要垃圾回收器没有回收软引用对象,这些对象就还可以被程序使用。
软引用可以用来实现内存敏感的高速缓存。
e.g. :
Person personA = new Person("Justin", "16");
SoftReference<Person> softRef = new SoftReference<Person>(personA);
personA = null;
对于新建的Person对象,有两个引用路径,一个是变量personA的强引用,一个是来自SoftReference对象的软引用。此事该对象为强可及对象。
将personA赋值为null结束对对象的强引用,则对象成为了软引用对象。
在软引用对象被回收前,可以通过get()重获对象的强引用:
Person personB = softRef.get();
在回收之后,get()方法得到的为null。
关于ReferenceQueue
SoftReference对象可以保存软引用,但是其也具有Java对象的一般性,当其保存的软可及对象被回收后,这个SoftReference对象也不具有存在价值,需要被清除。
这时候,我们可以利用ReferenceQueue来协助SoftReference对象的清除。
如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。如下:
ReferenceQueue rQueue = new ReferenceQueue<>();
SoftReference<Person> softRef = new SoftReference<Person>(personA, rQueue);
当softRef软引用的personA被回收时,softRef强引用的SoftReference对象会被列入ReferenceQueue。
调用ReferenceQueue的poll方法,如果不是空队列,则可以获取队列前面的Reference对象。
利用这个方法,我们可以检查哪个SoftReference所软引用的对象已经被回收。于是我们可以把这些失去所软引用的对象的SoftReference对象清除掉。
SoftReference ref = null;
while ((ref = (SoftReference) rQueue.poll()) != null) {
//清除ref
}
3、弱引用(WeakReference)
当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。
Java中用java.lang.ref.WeakReference类来表示。
e.g. :
Person personA = new Person("Justin", "16");
WeakReference<Person> wRef = new WeakReference<Person>(personA);
personA = null;
System.out.println("wRef.get() = " + wRef.get());
System.gc();//调用垃圾收集器回收内存空间
System.out.println("wRef.get() = " + wRef.get());
运行结果
wRef.get() = 姓名:Justin,年龄:16
wRef.get() = null
第二个输出为null证明弱引用关联的对象(无强引用或软引用关联)已经被回收掉。
弱引用也可以可ReferenceQueue关联使用。
4、虚引用(PhantomReference)
虚引用不影响对象的生命周期,如果一个对象与虚引用关联,则随时都可能被回收。
在java中用java.lang.ref.PhantomReference类表示。
虚引用必须和ReferenceQueue关联使用,当垃圾回收器准备回收一个对象时,若其有虚引用,则会将虚引用加入与之关联的引用队列。
程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否要将垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,就可以再所引用的对象被回收前采取必要的行动。