引用类型
强引用
强引用是常见的引用类型,通常通过new形式创建的对象都是强引用对象
Object o=new Object();
强引用作用的对象无论何时都不会被清理掉
只要强引用存在,GC永不回收掉被引用的对象,通过关键字new创建的对象所关联的引用就是强引用,只要这个强引用还指向某一对象,那就说明对象还一直存活着,垃圾回收器就不会碰,即使当内存不足时,JVM抛出OOM(OutOfMemoryError)异常也不会回收强引用的引用对象。
软引用、弱引用、虚引用这些都存在Java.lang.ref包中,父类为Reference类
Reference抽象父类的构造函数
//referent为引用指向的对象
Reference(T referent) {
this(referent, null);
}
//ReferenceQueue 可以理解为队列,在GC之前,将引用的对象放入Queue中,方便清理引用对象本身
Reference(T referent, ReferenceQueue<? super T> queue) {
this.referent = referent;
this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
}
举个例子:
Object o=new Object();
ReferenceQueue queue = new ReferenceQueue();
WeakReference wk = new WeakReference(o,queue);
此时,wk为弱引用,指向了o对象,o会在一定的时机被GC清理,但是wk对象工作依赖于Queue对象,当wk出现在Queue中,说明其指向的对象已经无效,可以放心清理
软引用:SoftReference
软引用所作用的对象,当发生GC操作时且内存充足时,不会回收软引用所作用的对象,当内存不足时,触发GC操作是,软引用所作用的对象会被回收
ReferenceQueue<A> queue = new ReferenceQueue<A>();
SoftReference<A> w = new SoftReference<A>(new A(), queue);
System.out.println(w.get());
System.out.println(w.isEnqueued());
System.out.println(queue.poll());
/**
* main.java.com.tulun.WeakHashMapGY02$A@1e3ac11b
* false
* null
*/
/**
* 划重点:
* //此处需要的内存,内存受限,不够用了,因此触发GC,回收软引用对象
*
*/
byte[] array = new byte[7*1024*1024+500*1024];
System.out.println(array[0]);
System.gc();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(w.get());
System.out.println(w.isEnqueued());
System.out.println(queue.poll());
弱引用:WeakReference
弱引用所作用的对象,当发生GC操作时,即使内存空间充足,GC操作也会回收弱引用所作用的对象
ReferenceQueue<A> queue = new ReferenceQueue<A>();
WeakReference<A> w = new WeakReference<A>(new A(), queue);
System.out.println(w.get());
System.out.println(w.isEnqueued());
System.out.println(queue.poll());
// main.java.com.tulun.WeakHashMapGY02$A@20724356
// false
// null
System.gc();
System.out.println("---------------------");
System.out.println(w.get());
System.out.println(w.isEnqueued());
System.out.println(queue.poll());
虚引用:phantonRefercence
虚引用是最弱的一种引用关系,一个对象是否有虚引用的存在,不会对对象生存时间构成影响,也无法通过虚引用来取得一个对象的实例,
虚引用存在可以来判断对象是否被回收
ReferenceQueue<A> queue = new ReferenceQueue<A>();
PhantomReference<A> ptr = new PhantomReference<A>(new A(), queue);
System.gc(); //此处启动GC,回收A对象,queue收到通知,该对象回收了
if(ptr.isEnqueued()){
System.out.println("ptr.isEnqueued()");
}else{
System.out.println("not ptr.isEnqueued()");
}