java的四种引用
强引用即为一般引用,软引用会在内存不足时回收,弱引用则是在GC时立即回收,虚引用一般用于标记GC对对象内存的操
作。
1、强引用
平时使用的都是强引用,把一个对象创建并赋给一个引用变量。
强引用有引用变量指向时,不会进行回收这种对象,直至oom。
如果想中断强引用和某个对象之间的关联,可以显示地将引用赋值为null,这样一来的话,JVM在合适的时间就会回收该对象,但也不会立马回收
2、软引用
会在oom之前根据算法优先回收软引用。
String s = new String("test SoftReference!");
SoftReference<String> sr = new SoftReference<String>(s);
/*
* 此时,对于该String对象,有一个来自s的强引用和一个来自sr的软引用,则该String对象时强可及对象。
* Java虚拟机的垃圾收集线程对软可及对象和其他一般Java对象进行了区别对待:
* 软可及对象的清理是由垃圾收集线程根据其特定算法按照内存需求决定的。
* 也就是说,垃圾收集线程会在虚拟机抛出OutOfMemoryError之前回收软可及对象,
* 而且虚拟机会尽可能优先回收长时间闲置不用的软可及对象,对那些刚刚构建的或刚刚使用过的“新”软可及对象会被虚拟机尽可能保留
*/
s=null;//如果s至为null,此时sr是软引用,会在oom之前进行回收
System.out.println(sr.get());// 在回收这些对象之前,我们可以通过get获得该实例的强引用,如果已经回收的话,get会返回null
/*
当软可及对象被回收之后,虽然这个SoftReference对象的get()方法返回null,但这个SoftReference对象已经不再具有存在的价值,
需要一个适当的清除机制,避免大量SoftReference对象带来的内存泄漏。在java.lang.ref包里还提供了ReferenceQueue。
如果在创建SoftReference对象的时候,使用了一个ReferenceQueue对象作为参数提供给SoftReference的构造方法
*/
ReferenceQueue<String> rq = new ReferenceQueue<String>();
SoftReference<String> sr2 = new SoftReference<String>(s, rq);
/*
在任何时候,我们都可以调用ReferenceQueue的poll()方法来检查是否有它所关心的非强可及对象被回收。
如果队列为空,将返回一个null,否则该方法返回队列中前面的一个Reference对象。
利用这个方法,我们可以检查哪个SoftReference所软引用的对象已经被回收。于是我们可以把这些失去所软引用的对象的SoftReference对象清除掉。常用的方式为:
*/
while ((sr2 = (SoftReference) rq.poll()) != null) {
sr2.clear();
}
3、弱引用
当gc时就会回收弱引用。
//弱引用,垃圾回收时就会回收弱引用
//弱引用1,返回分別為wr,null;如果不将ss=null,则返回为:wr,wr
String ss = new String("wr");
WeakReference<String> wr = new WeakReference<String>(ss);
System.out.println(wr.get());
ss=null;
System.gc();
System.out.println(wr.get());
//和上面返回一致。
//此处原因是:这里所说的被弱引用关联的对象是指只有弱引用与之关联,如果存在强引用同时与之关联,则进行垃圾回收时也不会回收该对象(软引用也是如此)。
WeakReference<String> wr2 = new WeakReference<String>(new String("wr2"));
System.out.println(wr2.get());
System.gc();
System.out.println(wr2.get());
4、虚引用
/*
* 虚引用的回收机制跟弱引用差不多,但是它被回收之前,会被放入ReferenceQueue中。
* 其它引用是被JVM回收后才被传入ReferenceQueue中的。由于这个机制,所以虚引用大多被用于引用销毁前的处理工作。
* 虚引用创建的时候,必须带有ReferenceQueue
*/
ReferenceQueue<String> queue = new ReferenceQueue<String>();
PhantomReference<String> pr = new PhantomReference<String>(new String("hello"), queue);
System.out.println(pr.get());