Java中的引用
引用类在垃圾回收工作的过程中有重要作用,垃圾回收机制会回收符合条件的对象的内存,而回收条件取决于指向该对象的引用类型。如果一个对象只有若引用指向它,垃圾回收器会立即回收该对象,这是一种急切的回收方式。相对的,如果有软引用指向它,垃圾回收机制只会在JVM需要内存时才回收这些对象。
强引用(StrongReference)
编程中使用的最简单的引用,就是普通引用,例如
String s = "abc"
s就是对字符串对象”abc”的一个强引用。任何被强引用指向的对象都不能被垃圾回收机制回收,这些对象都是程序中需要的。
A a1 = new A();
A a2 = a1;
a1和a2都是对new A()这块内存对象的强引用,只有当所有对这个对象(即a1,a2)的引用失效后,new A()所申请的内存才会被回收
软引用(SoftReference)
不能阻止垃圾回收机制,JVM需要时回收
应用场景:用来实现缓存,当JVM需要内存时,垃圾回收器就会回收这些只有被软引用指向的对象。
使用java.lang.ref.SoftReference类来表示,可以使用如下代码创建软引用
Counter counter = new Counter();
SoftReference softCounter = new SoftReference(counter);
counter = null; //此时垃圾回收机制不一定立即回收counter所指向的对象,因为该对象被softCounter软引用
弱引用(WeakReference)
不能阻止垃圾回收机制,立即回收
应用场景:存储元数据。例如存储ClassLoader引用,如果没有类被加载,那么也没有指向ClassLoader的引用。一旦上一次的强引用被去除,只有弱引用的ClassLoader就会被回收。
例如:WeakHashMap它是除HashMap和TreeMap之外,Map接口的另一种实现。它的键值都被封装成弱引用,也就是说,一旦强引用被删除,WeakHashMap内部的弱引用就无法阻止该对象被垃圾回收器回收。
使用java.lang.ref.WeakReference类来表示,可以使用如下代码创建弱引用
Counter counter = new Counter(); //创建一个强引用
WeakReference<Counter> weakCounter = new WeakReferencer<Counter>(counter); //创建一个指向该空间的弱引用
counter = null; //被垃圾回收机制回收,当强引用赋空后,若引用无法阻止垃圾回器的回收
虚引用(PhantomReference)
拥有虚引用的对象,可以在任何时候被垃圾回收器回收。
使用java.lang.ref.PhantomReference类来表示,可以使用如下代码创建
Counter counter = new Counter();
PhantomReference phantomCounter = new PhantomReference(counter);
counter = null;
引用队列(ReferenceQueue)
在创建任何弱引用、软引用和虚引用的过程中可以通过如下代码提供引用队列
ReferenceQueue refQueue = new ReferenceQueue();
Counter counter = new Counter();
PhantomReference phantomCounter = new PhantomReference(counter,refQueue);
引用实例将被添加在引用队列中,可以在任何时候通过查询该引用队列回收对象。一个对象的生命周期如图:
总结
- 残影引用、弱引用、软引用都是用来引用随时可能被回收的对象。区别是被回收期回收的激烈程度,由强到若。
- 残影引用是对象已经finalize或者执行完析构函数,只等内存马上回收了,最容易被回收。非常接近回收时机,就像残影会随物体消失而消失。
- 弱引用的对象是在正常情况下,回收器遇到就回收,是被积极回收的对象。
- 弱引用的对象是在正常情况下,回收器遇到就回收,是被积极回收的对象。