Java对象引用被划分为4种级别,这4种级别由高到低依次为:强引用、软引用、弱引用、和虚引用。
强引用
强引用是最普遍的引用,一般把一个对象赋给一个引用变量,这个引用变量就是强引用。
比如:
// 强引用 MikeChen mikechen=new MikeChen();
在一个方法的内部有一个强引用,这个引用保存在Java栈中,而真正的引用内容(MikeChen)保存在Java堆中。
如果一个对象具有强引用,垃圾回收器不会回收该对象,当内存空间不足时,JVM 宁愿抛出 OutOfMemoryError异常。
如果强引用对象不使用时,需要弱化从而使GC能够回收,如下:
//帮助垃圾收集器回收此对象 mikechen=null;
显式地设置mikechen对象为null,或让其超出对象的生命周期范围,则GC认为该对象不存在引用,这时就可以回收这个对象,具体什么时候收集这要取决于GC算法。
举例:
package com.mikechen.java.refenence; /** * 强引用举例 * * @author mikechen */ public class StrongRefenenceDemo { public static void main(String[] args) { Object o1 = new Object(); Object o2 = o1; o1 = null; System.gc(); System.out.println(o1); //null System.out.println(o2); //java.lang.Object@2503dbd3 } }
StrongRefenenceDemo 中尽管 o1已经被回收,但是 o2 强引用 o1,一直存在,所以不会被GC回收。
软引用
软引用是一种相对强引用弱化了一些的引用,需要用java.lang.ref.SoftReference 类来实现。
如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存。
先通过一个例子来了解一下软引用:
/** * 软引用举例 * * @author mikechen */ public static void main(String[] args) { Object obj1 = new Object(); // 建立软引用 SoftReference softRefer = new SoftReference<>(obj1); // 观察内存地址 System.out.println("obj1=" + obj1); System.out.println("softRefer=" + softRefer.get()); // obj1创建可以回收的条件 obj1 = null; try { byte[] bytes = new byte[6 * 1024 * 1024]; } catch (Throwable e) { System.out.println("===============>error:" + e.getMessage()); } finally { // 再次观察内存地址 System.out.println("obj1=" + obj1); System.out.println("softRefer=" + softRefer.get()); } }
内存充足,运行结果为:
内部不充足,比如:设置Run的JVM运行参数为:-Xmx5M,最为为5M的堆运行空间。
运行结果为:
内存不足的情况,软引用被回收了。
应用场景:
可以应用需要读取大量的本地数据,比如:图片、临时文件等。
软引用通常用在对内存敏感的程序中,比如:高速缓存就有用到软引用,内存够用的时候就保留,不够用就回收。
注意:
软引用对象是在jvm内存不够的时候才会被回收,我们调用System.gc()方法只是起通知作用。
JVM什么时候扫描回收对象是JVM自己的状态决定的,就算扫描到软引用对象也不一定会回收它,只有内存不够的时候才会回收。
弱引用
弱引用的使用和软引用类似,只是关键字变成了 WeakReference:
MikeChen mikechen = new MikeChen(); WeakReference<MikeChen> wr = new WeakReference<MikeChen>(mikechen );
弱引用的特点是不管内存是否足够,只要发生 GC,都会被回收。
举例说明:
package com.mikechen.java.refenence; import java.lang.ref.WeakReference; /** * 弱引用 * * @author mikechen */ public class WeakReferenceDemo { public static void main(String[] args) { Object o1 = new Object(); WeakReference<Object> w1 = new WeakReference<Object>(o1); System.out.println(o1); System.out.println(w1.get()); o1 = null; System.gc(); System.out.println(o1); System.out.println(w1.get()); } }
输出为:
弱引用的应用
WeakHashMap
public class WeakHashMapDemo { public static void main(String[] args) throws InterruptedException { myHashMap(); myWeakHashMap(); } public static void myHashMap() { HashMap<String, String> map = new HashMap<String, String>(); String key = new String("k1"); String value = "v1"; map.put(key, value); System.out.println(map); key = null; System.gc(); System.out.println(map); } public static void myWeakHashMap() throws InterruptedException { WeakHashMap<String, String> map = new WeakHashMap<String, String>(); //String key = "weak"; // 刚开始写成了上边的代码 //思考一下,写成上边那样会怎么样? 那可不是引用了 String key = new String("weak"); String value = "map"; map.put(key, value); System.out.println(map); //去掉强引用 key = null; System.gc(); Thread.sleep(1000); System.out.println(map); }}
当key只有弱引用时,GC发现后会自动清理键和值,作为简单的缓存表解决方案。
ThreadLocal
static class ThreadLocalMap { static class Entry extends WeakReference<ThreadLocal<?>> { Object value; Entry(ThreadLocal<?> k, Object v) { super(k); value = v; } } //......}
ThreadLocal.ThreadLocalMap.Entry 继承了弱引用,key为当前线程实例,和WeakHashMap基本相同。
虚引用
虚引用”顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。
虚引用也称为“幽灵引用”或者“幻影引用”,它是最弱的一种引用关系。
虚引用需要java.lang.ref.PhantomReference 来实现:
A a = new A(); ReferenceQueue<A> rq = new ReferenceQueue<A>(); PhantomReference<A> prA = new PhantomReference<A>(a, rq);
虚引用主要用来跟踪对象被垃圾回收器回收的活动。
虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。
Java引用总结
java4种引用的级别由高到低依次为:强引用 > 软引用 > 弱引用 > 虚引用。
- 强引用:最常见,垃圾收集器不会回收此类对象。
- 软引用:适合实现缓存,在内存不足时回收对象。
- 弱引用:适合避免内存泄漏,在下一次垃圾收集时回收对象。
- 虚引用:用于跟踪对象的回收情况,无法通过引用获取对象。
陈睿mikechen
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》