对象已死么

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_18975791/article/details/85392610

    垃圾回收前需要知道哪些对象需要被收集,就需要知道哪些对象是死了还是活的。下面就是知道哪些对象是死是活的算法。

引用计算法

    引用计数算法是每次使用一个对象的时候就加1,不使用后就减1,为0了,就说明这个对象死了。但是java中没有使用引用计数算法,因为java中存在着循环引用的问题,所以不行。

可达性分析算法

    通过一系列称为GC roots的对象作为起始点,开始搜索下面节点,当一个对象不能抵达GC roots时,这个对象就不可用,被判定为可回收对象。在java语言中,可作为GC roots的有1:虚拟机栈中引用的对象;2.方法区中类静态属性引用对象;3.方法区中常量引用的对象;4.本地方法栈中jni引用的对象。

再谈引用

引用分为四种:强引用;软引用;弱引用;虚引用;

强引用:强引用类似于Object obj =new Object();只要强引用存在,就不会被回收。

软引用:是用来描述一些还有用,但是非必须的对象。在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围进行二次回收,如果还是没有足够的空间,那么将会抛出异常。softreference类来实现软引用。

弱引用:弱引用对象是也是用来描述非必须对象的,但是比软引用还要弱,在垃圾收集器下一次进行回收的时候,无论内存是否足够,都会被收集。weakreference来实现弱引用。

虚引用:虚拟引用也称为幽灵引用,幻影引用。最弱的一种引用。一个对象是否有虚拟引用的存在,完全不会对其存在的时间产生影响,也无法通过一个虚拟引用得到一个对象实例。为一个对象设置一个虚拟引用关联的唯一目的就是这个对象被回收的时候,收到一个系统通知。

生存还是死亡

一个对象即使在可达性分析算法中被标记为不可达对象,这个时候只是被判定为缓刑,要等到第二次被判定,才有可能被回收。第一次标记的同时,还会进行一次筛选,筛选的条件就是此对象,是否有必要执行finalize()方法。当对象没有覆盖finalize()或者finalize()已被虚拟机调用,,就会被虚拟机视为没有必要执行。

    如果确定需要执行finalize(),那么这个对象会被放进一个F-queue的队列,,由虚拟机建立一个低优先级的线程进行执行。这里的执行只是触发,并不会等他运行结束,这样做的原因是当这个对象执行很慢,或者发生了死循环,那么可能会导致内存回收系统的奔溃,finalize()方法是对象逃脱死亡的最后一次机会,只要他与引用链上的任何一个对象链接上就行了。GC进行第二次,小规模的标记,即将回收,那么基本就会被回收,逃脱不了。一个对象的finalize()被执行,但是他仍然可以存活。这个方法是对c/c++程序的一种妥协,用try/catch等能做的更好,完全忘掉这个方法。

回收方法区

    回收方法区一般没有垃圾收集器,这个地方垃圾收集的性价比太低,所以一般不处理这里。但是这里还是有垃圾收集器,有些参数可以设置,进行回收。

    在大量使用反射,动态代理,CGLib等bytecode框架。动态生成jsp以及OSGi这类频繁自定义类加载的场景都需要虚拟机具备类卸载的功能,以保证永久带不会溢出。

猜你喜欢

转载自blog.csdn.net/qq_18975791/article/details/85392610