【对象的生死判定】

我只是一个虾纸丫 提交于 2020-01-17 05:33:45

垃圾回收

JAVA有一个很大的好处就是,不用自己管理内存,虚拟机帮助开发者完成了这些操作。所以这是好是坏呢?不敢苟同。

对象生死

垃圾的定义:垃圾回收肯定是要知道怎么定义垃圾。简单点说就是,已经被用过了,并且不会再用了,而且还在内存里面的对象,就是垃圾。因为他占着资源。
如何判断垃圾:现在常用的两种方法,引用计数法和可达性分析。
引用计数:这个其实是一个很不错的方法,思想也很简单,如果一个对象被引用了,那么就给它的生命力++,如果引用它的人生命结束了,那么它的生命就减一。最后看看谁生命值是0,那么就判定他是垃圾。嗯,不错的一个方案,实现起来也很简单。
引用计数存在的问题
在这里插入图片描述但是在这种情况下,就不是很好了,这种情况被称之为循环引用,A引用了B,B又引用了A,那么他俩的生命力得到了对方的加持,一直不为0,就一直存活。
可达性分析:其实这种情况,抽象一下就是出现了环路。从图论的角度来看,这个引用关系构成的图应该是一个DAG(有向无环图),一旦环路存在,那么就会出现上述问题。继续考虑,其实都考虑到图论这来了,那么这个问题的解就显而易见了:所有的应用关系构成了有向图,如果有些连通分量里面的所有点都没被用过,那么这个连通分量可以被丢弃。
在这里插入图片描述比如这个图,左边存在环路,右边也可能存在。虚拟机中有一个GC ROOT,即使这些点的计数不为0,当GC ROOT不可达的时候,那么这些连通分量里面的对象依然会被回收。

死缓

再给个机会:如果计数为0或者不可达就要被判定死刑了吗?似乎不太合理,因为太绝情了。因为虽然在当前状态不可达或者没有人引用,没准下一状态里面就有人用了呢?这是很可能的,如果直接销毁掉用了再创建这其实还是比较浪费的,因为做了不必要的工作,但是一直呆在内存里也不是很合适,所以虚拟机决定再给对象一个机会,如果对象能够实现自我的救赎,那么就不判死刑了,否则就销毁掉。虚拟机的设计充满了人道主义
死缓:当对象不可达,就进入了死缓的状态。
第一次筛选:进入死缓状态的对象,虚拟机会进行第一次筛选,筛选的条件是判断该对象有没有必要执行finalize()方法,如果当前对象没有覆盖finalize()方法,或者该方法被虚拟机调用过一次了,虚拟机就会认为没有必要执行。对于没必要执行的对象,额,不好意思,那就是真的死刑了。对象直接被销毁
第二次筛选:对于有必要执行finalize()方法的对象,会被丢人一个叫做F_Queue队列中,之后,虚拟机会创建一个Finalizer线程然后开始来销毁对象,当然这个线程优先级很低,并且不保证能够执行完。在死亡即将到来之时,如果队列中的对象能够在这个过程中和GC ROOT 可达的对象建立连接,那么成功自我救赎。虚拟机在第二次标记时,会把它移出队列,其他的也是死刑。
有趣的是,finalize()方法只会被调用一次,也就是这种自我救赎的方式只能用一次,第二次被就没用了。一般不建议使用finalize()方法去拯救对象,因为它的开销是比较大的。

以上就是虚拟机对对象生死的判定方法,下一篇讲述垃被垃圾回收的具体机制。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!