强引用是常见的引用类型,通常通过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中,说明其指向的对象已经无效,可以放心清理
软引用所作用的对象,当发生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());
弱引用所作用的对象,当发生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());
虚引用是最弱的一种引用关系,一个对象是否有虚引用的存在,不会对对象生存时间构成影响,也无法通过虚引用来取得一个对象的实例,
虚引用存在可以来判断对象是否被回收
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()"); }