Java的四种引用,强弱软虚,用到的场景。
java引用和java回收机制的关系
当java虚拟机(JVM)觉得内存不够的时候,会触发垃圾回收操作(GC),清除无用的对象,释放内存。可是如何判断一个对象是否为垃圾呢?其中一个办法就是计算指向该对象的数量,如果数量为零,那么该对象就是垃圾(Thread对象除外),其他的就不能回收,如果回收了这些没有被引用的对象后还是没法满足内存需求,怎么办?java把引用分位四种类型,垃圾回收器会尝试回收弱引用的对象。
按照一个对象的引用可达(Reachable)强度,有强到弱分为五大类,如下:
- 强可达(Strong Reachable)
- 软可达(Soft Reachable)
- 弱可达(Weak Reachable)
- 虚可达(Phantom Reachable)
- 不可到达(Ureachable)
java回收器会优先回收可达强度较低的对象,另外两个重要的点:
- JVM保证抛出out of memory之前,清理所有的软引用对象
- 强可达的一定不会被清理
java中的4中引用
- 强引用(StrongReference)
强引用可以直接访问目标对象。
强引用所指向的对象在任何时候都不会被系统回收。
强引用可能导致内存泄漏。
- 软引用(SoftReference)
Object obj = new Object();
SoftReference<Object> softObj = new SoftReference(obj);
//获取软引用所引用的对象
Object objSoft = softObj.get();
软引用有以下特征:
软引用使用 get() 方法取得对象的强引用从而访问目标对象。
软引用所指向的对象按照 JVM 的使用情况(Heap 内存是否临近阈值)来决定是否回收。
软引用可以避免 Heap 内存不足所导致的异常。
当垃圾回收器决定对其回收时,会先清空它的 SoftReference,也就是说 SoftReference 的 get() 方法将会返回 null,然后再调用对象的 finalize() 方法,并在下一轮 GC 中对其真正进行回收。
- 弱引用(WeakReference)
弱引用和软引用类似,区别在于,只具有弱引用的对象拥有更短的生命周期,垃圾回收器线程扫描他所管辖的内存区域时,一旦发现弱引用对象不管内存空间够不够都会回收,不过垃圾回收线程优先级很低,因此不会很快发现。
弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果持有弱引用的对象呗回收了,java虚拟机就会把这个弱引用加入到与之关联的引用队列中。完全可以通过和 SoftReference 一样的方式来操作 WeakReference,这里就不再复述。
弱引用有以下特征:
弱引用使用 get() 方法取得对象的强引用从而访问目标对象。
一旦系统内存回收,无论内存是否紧张,弱引用指向的对象都会被回收。
弱引用也可以避免 Heap 内存不足所导致的异常。
- 虚引用(PhantomReference)
Object obj = new Object();
ReferenceQueue<Object> refQueue = new ReferenceQueue<Object>();
PhantomReference<Object> phanRef = new PhantomReference<Object>(obj, refQueue);
// 调用phanRef.get()不管在什么情况下会一直返回null
Object objg = phanRef.get();
// 如果obj被置为null,当GC发现了虚引用,GC会将phanRef插入进我们之前创建时传入的refQueue队列
// 注意,此时phanRef所引用的obj对象,并没有被GC回收,在我们显式地调用refQueue.poll返回phanRef之后
// 当GC第二次发现虚引用,而此时JVM将phanRef插入到refQueue会插入失败,此时GC才会对obj进行回收
Reference<? extends Object> phanRefP = refQueue.poll();