从JDK源码理解java引用

虚引用、弱引用、软引用的实现

ReferenceHandler线程

引用队列的实现

总结

参考资料

java中的引用

JDK 1.2之后,把对象的引用分为了四种类型,分别为:强引用、软应用、弱引用和虚引用,以方便控制java对象的生命周期。

强引用

强引用是工作开发中使用最多的引用类型。比如声明一个字符串变量String str="abc"。只要对象与强引用关联,JVM就不会回收这个对象,即不会回收这个区域
的内存。
如果我们希望回收abc这个对象,那么就需要显示的将str设置为null,即str=null。那么jvm就会在下一次gc时回收这部分内存区域。

2.软引用

软引用可以用来描述一些非必须的对象,java中使用SoftRefence来表示软引用。对于软引用的生命如下:

SoftRefence<String> str = new SoftRefence<String>(new String("abc")); 或者 SoftReference<String> str=new SoftReference<>("abc");

对于软引用关联的对象,只要系统内存足够,就不会回收这部分内存,只有当系统要发生内存泄漏之前才会将只与软引用关联的对象进行回收,当回收完之后内存还不足时
会抛出内存溢出的异常。

弱引用

弱引用用来描述非必须的对象。使用方法如下:

WeakReference<String> str=new WeakReference<>("abc"); 或者 WeakReference<String> str=new WeakReference<String>(new String("abc"));

对于只使用弱引用描述的对象,这个对象可以通过弱引用用找到,但是他只能存活到下一次gc之前,也就是说,只被弱引用关联的对象,在下一次gc时,会被垃圾回收掉。
验证如下:

public class Weak { public static void main(String[] args) throws InterruptedException { String str="abc"; WeakReference<String> weakStr=new WeakReference<>(str); System.out.println("=======当对象同时被强引用和弱引用关联,执行一次gc======"); System.gc(); System.out.println(weakStr.get()); System.out.println("========当对象只与弱引用关联======"); str = null; System.out.println(weakStr.get()); System.out.println("========再次执行gc======"); System.gc(); Thread.sleep(10000); System.out.println(weakStr); System.out.println(weakStr.get()); } }

结果如下:

=======当对象同时被强引用和弱引用关联,执行一次gc====== abc ========当对象只与弱引用关联====== abc ========再次执行gc====== java.lang.ref.WeakReference@1b6d3586 abc

咦没回收!!!再来看个例子

public class Weak { public static void main(String[] args) throws InterruptedException { Integer i=new Integer(10); WeakReference<Integer> weakStr=new WeakReference<>(i); System.out.println("=======当对象同时被强引用和弱引用关联,执行一次gc======"); System.gc(); System.out.println(weakStr.get()); System.out.println("========当对象只与弱引用关联======"); i = null; System.out.println(weakStr.get()); System.out.println("========再次执行gc======"); System.gc(); Thread.sleep(10000); System.out.println(weakStr); System.out.println(weakStr.get()); } }

结果如下:

=======当对象同时被强引用和弱引用关联,执行一次gc====== 10 ========当对象只与弱引用关联====== 10 ========再次执行gc====== java.lang.ref.WeakReference@1b6d3586 null

回收了!!!为什么??

虚引用

虚引用是引用关系中最弱的一种引用,也被称为幽灵引用或者幻影引用。一个对象是否存在虚引用,完全不会对其生存时间构成影响,也无法通过虚引用来获取一个对象实例,
为对象设置虚引用的目的是为了能够在对象被回收器回收时得到一个通知。
虚引用的使用必须和一个引用队列绑定,使用举例如下:

PhantomReference<String> str= new PhantomReference<>("abc",new ReferenceQueue<>()); 引用队列

引用队列提供了一种可以直观了解垃圾回收的方式。引用队列可以和软引用、弱引用和虚引用搭配使用,当JVM进行垃圾收集的时候会将引用对象加入到引用队列中,
即:在引用队列中的节点(引用类型的对象)所关联的对象已经被回收。例子如下:

public static void main(String[] args) { Object object=new Object(); ReferenceQueue<Object> objectReferenceQueue=new ReferenceQueue<>(); WeakReference<Object> objectWeakReference=new WeakReference<>(object,objectReferenceQueue); object=null; System.gc(); System.out.println(objectWeakReference.get()); System.out.println(objectReferenceQueue.poll()); }

输出结果如下:

objectWeakReference.get()====null objectWeakReference====java.lang.ref.WeakReference@1b6d3586 objectReferenceQueue.poll()====java.lang.ref.WeakReference@1b6d3586

上面的例子中object对象关联了一个弱引用objectWeakReference。从输出结果来看,当object对象垃圾回收之后,objectWeakReference对象被加入到了引用队列当中。

虚引用、弱引用、软引用的实现

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwssgs.html