强软弱虚四种引用
1.强引用(Strong Reference):
如果一个对象具有强引用,它就不会被垃圾回收器回收。即使当前内存空间不足,JVM也不会回收它,而是抛出 OutOfMemoryError 错误,使程序异常终止。如果想中断强引用和某个对象之间
的关联,可以显式地将引用赋值为null,这样一来的话,JVM在合适的时间就会回收该对象
Object obj = new Object(); //只要obj还指向Object对象,Object对象就不会被回收
obj = null; //手动置null
2.软引用(Soft Reference):
在使用软引用时,如果内存的空间足够,软引用就能继续被使用,而不会被垃圾回收器回收。只有在内存不足时,系统则会回收软引用对象,如果回收了软引用对象之后仍然没有足够的内存>,才会抛出内存溢出异常。
在 JDK1.2 之后,用java.lang.ref.SoftReference类来表示软引用。
使用场景:
这种特性常常被用来实现缓存技术,比如网页缓存,图片缓存等。
3.弱引用(Weak Reference):
具有弱引用的对象拥有的生命周期更短暂。因为当 JVM 进行垃圾回收,一旦发现弱引用对象,无论当前内存空间是否充足,都会将弱引用回收。不过由于垃圾回收器是一个优先级较低的线程
,所以并不一定能迅速发现弱引用对象。
在 JDK1.2 之后,用 java.lang.ref.WeakReference 来表示弱引用。
使用场景:
在静态内部类中,经常会使用虚引用。例如:一个类发送网络请求,承担 callback 的静态内部类,则常以虚引用的方式来保存外部类的引用,当外部类需要被 JVM 回收时,不会因为网络请
求没有及时回应,引起内存泄漏。
4.虚引用(Phantom Reference):
顾名思义,就是形同虚设,如果一个对象仅持有虚引用,那么它相当于没有引用,在任何时候都可能被垃圾回收器回收。
虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这>个虚引用加入到与之关联的引用队列中。
在 JDK1.2 之后,用 PhantomReference 类来表示。
使用场景:
jdk中直接内存的回收就用到虚引用,由于jvm自动内存管理的范围是堆内存,而直接内存是在堆内存之外(其实是内存映射文件,自行去理解虚拟内存空间的相关概念),所以直接内存的分>配和回收都是有Unsafe类去操作,java在申请一块直接内存之后,会在堆内存分配一个对象保存这个堆外内存的引用,这个对象被垃圾收集器管理,一旦这个对象被回收,相应的用户线程会收到>通知并对直接内存进行清理工作。
虚引用在java中的应用
可以用来管理堆外内存
当对象被回收时,通过Queue可以检测到,然后清理堆外内存,如下图所示:
观察下面代码:
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
/**
* 虚引用
*/
public class PhantomRefTest {
private static ReferenceQueue<PhantomRefTest> queue = new ReferenceQueue<>();
public static void main(String[] args) {
PhantomReference<PhantomRefTest> reference = new PhantomReference<>(new PhantomRefTest(), queue);
System.out.println(reference.get());
System.out.println(queue.poll());
System.gc();
System.out.println(reference.get());
System.out.println(queue.poll());
}
}
执行结果如下:
可以看出在JVM进行gc之后,虚引用对象进入了队列,然后JVM就可以通过这个队列检测到发生了垃圾回收,再进行对堆外内存的处理。