在JDK1.2后,java对引用的概念进行了扩充。按照引用强度依次从强到弱分为:强引用、软引用(SoftReference)、弱引用(WeakReference)、虚引用(PhantomReference)用四种。
强引用:最常见的,不会被GC回收的对象,如 Object obj = new Object();
软引用:可有可无的对象,如果内存空间足够,GC就不会去回收这个对象,如果内存不足,就会回收,软引用可有和ReferenceQueue(引用队列)联合使用,如果软引用所引用的对象呗GC回收,JVM就会把这个软引用加入到引用队列中。
public static void soft() throws Exception{
Object obj = new Object();
ReferenceQueue rq = new ReferenceQueue<>();
SoftReference sr = new SoftReference(obj, rq); //创建关于obj的软引用,使用引用队列
System.out.println(sr.get()); //get方法会输出这个obj对象的hashcode
System.out.println(rq.poll()); //输出为null
obj = null;
System.gc();
Thread.sleep(200); //因为finalizer线程优先级很低,所以让线程等待200ms
System.out.println(sr.get()); //因为堆空间没满,可有可无的特性,所以还是会输出这个obj对象的hashcode
System.out.println(rq.poll()); //自然队列为null
}
弱引用:也是描述可有可无的对象,和软引用不同的是,它的生命周期更短,在GC的过程中,一旦发现有弱引用的对象,不管当前内存空间是否足够,都会回收它的内存。 真是因为这个特性,所以弱引用常用于Map数据结构中,引用占用空间内存较大的对象。
public static void weak() throws Exception{
Object obj = new Object();
ReferenceQueue rq = new ReferenceQueue<>();
WeakReference wr = new WeakReference(obj,rq);
System.out.println(wr.get());
System.out.println(rq.poll());
obj = null;
System.gc();
Thread.sleep(200);
System.out.println(wr.get()); //这时候会输出null
System.out.println(rq.poll()); //rq队列里也会存放这个弱引用,输出它的hashcode
}
虚引用:也成幽灵引用,他的构造方法必须传递RefenceQueue参数,当GC准备回收一个对象时,发现它还有虚引用,就会在回收前,把虚引用加入到引用队列中,程序可以通过判断队列中是否加入虚引用来判断被引用的对象是否将要GC回收,从而可以在finalize方法中采取措施。