如何判断对象已死

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

在我们要判断对象是否是生存还是死亡时,我们要先了解如下知识点:

可达性分析算法(用于判断对象是否存活)

算法的思想:以上图为模型作为理解,一系列GC Roots的对象作为初始点,按照节点向下搜索,搜索经过的路线成为引用链,

当一个对象到GC Roots没有任何的引用链的话,则表明这个对象不可用,如图object4、object5、object6虽然互相关联,但是它们还是都会被当作回收对象进行回收。

在Java语言里有以下几种可以被作为GC Roots对象:

1.虚拟机栈(栈表中的本地变量表)中引用的对象

2.方法区中静态属性引用的对象

3.方法区常量引用的对象

4.本地方法栈中JNI(Native方法)引用的对象

强引用、软引用、弱引用、虚引用

引用:在JDK1.2之前只区分:有无引用,而在JDK1.2之后,则增加了这四类区分。

强引用:类似->    Object obj = new Object()

注意:只要强引用还在,被引用的对象永远不会被垃圾收集器进行回收。

软引用:描述还有用但是并非是必需的对象。

注意:在将发生内存溢出之前,会对此引用对象进行第二次回收,如果没有足够内存回收,将会抛出内存溢出异常,JDK1.2提供了

SoftReference类来实现软引用。

弱引用:非必须对象,强度比软还弱。

注意:被此应用关联到的对象只能生存到下一次垃圾收集发生之前。不管当前的内存是否充足,都会回收只被弱引用关联的对象。

虚引用:最弱的。只有一个用处,其他不用考虑。

用处:被此应用关联到的对象在进行回收时会收到系统通知。同样在JDK1.2之后,提供了PhantomReference类来实现虚引用。

介绍了这么多,接下来我来分析如何判断对象是否存活?并介绍该对象如何自救?

其实在前面介绍的可达性分析中,如果此对象是不可达的,此对象也并非一定会死亡。

通过下面的步骤分析该对象是如何自救的?

1 先进入缓刑阶段,此过程会对该对象进行两次判定,和上面画的图一样,它有两条路选择,要么进去安全区(与GC Roots相连接的引用链里面),不然进去未知区里面,进去里面要么等着被处理掉(是否有必要执行finalize()方法),要么自救。
2 如果对象不幸进入未知区,如果被判定为有必要执行,该对象将进入一个F-Queue的队列中去,然而,进去之后,还要进行逃脱(自救)不然就被回收掉。
3 finalize()方法是最后一根救命草,抓得住了,就得救了,怎么抓能?很简单,重新与与引用链中得任意对象进行关联即可,不然就真的没救了。
4 最后有一个残酷的现实:即当对象没有覆盖此方法或已经被虚拟机调用过,那么都将视为没有必要执行。
5 注意:我们所说的执行并非执行到底,而是一个触发,触发之后可能出现对象在此方法执行时出现执行缓慢或者死循环等问题,这样会导致该队列(F-Queue的其他对象一直处于等待的状态,甚至导致整个系统崩溃)

现实中我们不应该去选择,而应该去避免。

垃圾收集:

永久代的收集主要回收两部分内容:废弃常量和无用的类

废弃常量:定义了一个常量却没去用到它,将被清除。

如何判定一个类是否无用?

        1.该类所有的实例都已经被回收,也就是Java堆中不存在该类的任何实例。

        2.加载该类的ClassLoader已经被回收。

        3.该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

这里的所说的可以并非是一定的意思,可控制的。

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

猜你喜欢

转载自blog.csdn.net/qq_41723615/article/details/88412149
今日推荐