当触发垃圾回收时,GC(垃圾回收)线程会根据跟搜索算法判断这个对象是否可达(即GCroot到这个对象之间时否有一条可达的引用链)。
如果可达,很幸运,你继续活着。
如果不可达,当然你不一定百分之一百就死掉了,在杀死一个对象之前,GC线程至少会对这个对象标记两次,
垃圾回收线程在对所有不可达的对象进行第一次标记后,会进行一个筛选,
筛选的条件是:是否执行这个对象的fianlize()方法。这个方法是Object对象自带的,所以每个对象也都包含此方法。
如果 对象的fianlize()方法被这个对象覆盖,或者这个对象的finalize()方法是否被虚拟机调用过。
则则被判断为很有必要调用对象的fianlize()方法。
如果被判断有必要执行对象的fianlize()方法,那么这个对象会被放入一个叫做F-Queue的队列中,
稍后会有虚拟机自动创建一个低优先级的fianlizer的线程,此线程回去触发队列中对象的fianlize()方法,
但是不保证等待对象的finalize()方法执行结束,因为万一对象的这个方法执行的非常缓慢,甚至极端的出现了死循环,
会影响F-Queue队列中的其他对象的处理,甚至导致整个垃圾回收崩溃。
因为对象的finalize()方法会被调用,又可以被重写,所以这是这些对象逃离升天不被垃圾回收kill的唯一的一次机会。
如果这些对象重写了自己的finalize()方法,并且顺利的把自己重新复制给一个新的引用,
这样的话就有了GCroot指向此对象,再第二次进行垃圾回收的时候就可以逃离升天了。
如果再这个方法中没有给自己找一个新的归属,就真的离死亡不远了,GC线程的死亡之镰会挥舞向你。
注意:请尽量不要复写这个finalize(),用它来拯救对象,因为运行他的代价太大,不确定性也很大,对象的执行顺序也不一样。
至于用它来关闭资源,这只是一个自我安慰。try catch finally 效果更好也更容易把控。所以可以把这个方法完全忘记。
GCroot主要包括以下几类:
1.虚拟机栈(栈中的本地变量表)中引用的对象。
2.方法区中类静态属性引用的对象。
3.方法区中常量引用的对象。
4.本地方法栈中JNI(即常说的native方法中)引用的对象