大部分由new操作符创建的java对象实例采用强引用方法:
Object o = new Object();// 产生强引用o = null; // 结束引用,对象将在GC时被回收
指向对象的强引用指针是否存在决定了强引用对象是否存活,当没有强引用指针指向仅用于强引用的对象(将强引用赋null)时,其就会在GC时被回收。
弱引用,软引用和虚引用与GC过程紧密相关,其区别也在于使得对象在面对GC时有不同的行为模式。
软引用SoftReference
软引用是上述三者中最“强”的引用,其通过java.lang.ref.SoftReference类实现:
@Testpublic void softRefTest() {TestClass o = new TestClass();SoftReference<TestClass> sr = new SoftReference<>(o);o = null;System.out.println(sr.get());System.gc();System.out.println(sr.get());}static class TestClass {String str() {return "a str";}}
此处,软引用sr能在硬引用o置null之后继续引用到TestClass对象实例,且在GC过程之后,这一引用仍然存在。此处可以看出软引用与弱引用相比更“硬”的一点在于,其引用的对象只会在内存不足时被GC收集。而后者只要面临GC,就会被收集。
同时,每个软引用都会维护最后访问的时间戳,此时有特殊设计的垃圾收集器就能根据时间戳来选定软引用清理对象。
基于这种特性,软引用可以用于应用级别的缓存设计。可以将数据量较大但使用时间局部性较强的数据设为软引用,在内存不足时,其就会自动被清理。
弱引用WeakReference
由上节,同样引用非必需对象的弱引用,在面对GC过程时,无论内存是否充足,总是会被垃圾回收器回收。
@Testpublic void weakRefTest() throws InterruptedException {TestClass o = new TestClass();WeakReference<TestClass> wr = new WeakReference<>(o);o = null;System.out.println(wr.get());System.gc();Thread.sleep(1000);System.out.println(wr.get());}static class TestClass {String str() {return "a str";}}
上述代码中,在调用GC进程并等待一段时间后(GC也许不会立刻进行),弱引用对象就无法访问到TestClass实例,实际上它已经被收集。
弱引用可用于以下场景:如果想偶尔获取某个对象,但不影响其生命周期和垃圾收集(这个对象往往比较大),则用弱引用指向该对象,从而使得该对象能够在存在强引用或是无强引用但还未GC时能够被弱引用访问到,并且其生命周期并不会被弱引用改变。
