java基础篇——强引用、软引用、弱引用、虚引用

线程调用方法时,会从虚拟机栈中获取一个栈帧作为本次方法调用的内存区域;方法中声明的引用会存放在这个栈帧中(也就是一次压栈的过程),如果创建引用是方式是用new关键词创建的那么引用指向的实例保存在堆中,方法执行完会自动释放掉栈帧所占用的内存,当然也包括引用;而实例则需要根据与之关联的引用来决定是否可以被gc回收掉,如果这个实例已经没有引用关联了,代表这个实例是可以被gc回收掉的(具体回收时机依据垃圾回收策略)。
引用分强引用、软引用、弱引用、虚引用;不同的引用会影响该引用指向的实例的回收时机;下面依次讲解
一、强引用
代码:在这里插入图片描述
以这种方式创建的引用关联我们也称之为强引用。发生gc时如果实例存在强引用,那么该实例在本次gc后不会回收实例(即使发生oom也不会);并且在多次gc后该实例继续存活则将该实例移至堆内存中的survivor区或年老区。

二、软引用
代码:在这里插入图片描述
代码中清除了实例的强引用关联,那么目前只关联了一个软引用;gc发生的时候不会回收实例,但在抛出oom异常情况前,gc会回收实例来释放内存尝试防止oom的发生。

三、弱引用
代码:在这里插入图片描述
代码中清除了实例的强引用关联,那么目前只关联了一个弱引用;这种情况下gc是可以回收掉实例的。
四、虚引用
代码:
在这里插入图片描述
代码中可以看到是无法通过虚引用访问实例的,虚引用的作用仅仅是确保对象被finalize以后做某些事情的机制。如果一个实例仅关联了虚引用, 那么它就和没有任何引用一样,是可以被gc回收的。虚引用必须和引用队列联合使用。当gc准备回收一个实例时,如果发现它还有虚引用,就会在回收实例的内存之前,把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到 引用队列,那么就可以在所引用的对象的内存被回收之前采取一些程序行动。

应用场景:
因为gc对拥有软引用和弱引用实例特殊的回收机制,可以通过它们来控制实例的生命周期达到缓存的效果,根据实际需求选择用哪种引用来控制实例的生命周期,我们可以通过这样的方法在保证不发生oom的情况下将业务数据放在内存中获取提高业务的响应速度。虚引用可用来跟踪对象被垃圾回收器回收的活动,当一个虚引用关联的对象被垃圾收集器回收之前会收到一条系统通知。

猜你喜欢

转载自blog.csdn.net/qq_34812009/article/details/89477151