01 介绍
在垃圾回收之前 会调用对象的finalize()
finalize()是bject类的方法,子类重写finalize()在对象被回收时进行资源的释放和清理工作,如关闭文件/套接字/数据库连接等
程序员不要主动调用finalize(),jvm的垃圾回收机制会调用,原因如下
finalize()可能会到导致对象复活
finalize()执行没有保障,执行这个方法的线程优先级比较低,极端情况下如不发生GC,finalize()没有执行机会
糟糕的finzlize()会严重影响GC性能
02 对象状态
(1) 可触及的 从根节点开始可以到达这个对象 可达的 不能回收
(2) 可复活的 对象的所有引用都被释放 但对象可能在finalize()中复活
(3) 不可触及的 对象的finalize()被调用 并且没有复活
不可触及的永远不可能被复活 因为finalize()只会被调用一次
这个状态的对象可以被回收
以上3种状态是由于finalize()方法的存在
只有在对象不可触及时才可以被回收
03 过程
判定一个对象是否可回收 , 或经历下面几个过程(两次标记)
(1) 若对象到GC Root没有引用链,则进行第一次标记
(2) 若对象没有重写fialize()或已经被调用过了,则对象被判定为不可触及
(3) 若对象重写finalize()且未执行过,对象被插入到F-Quene队列中 ,由虚拟机创建的低优先级Finalizer线程触发finalize()
(4) finalize()是对象逃脱死亡的最后机会,GC会对F-Quene队列中的对象进行第二次标记,在finalize()中若对象与引用链上任何一个对象建立了联系,在第二次标记时对象会被移除
(5) 之后若对象再次不可达,finalize()已经被调用过了不能再调用了,对象就变成不可触及的状态了
04 复活代码
public class FinalizationTest {
public static FinalizationTest obj;
@Override
protected void finalize() throws Throwable {
obj = this;
}
public static void main(String[] args) {
try {
obj = new FinalizationTest();
obj = null;
System.gc();
System.out.println("第1次gc");
// 因为Finalizer线程优先级很低,暂停2秒,以等待它
Thread.sleep(2000);
if (obj == null) {
System.out.println("obj is dead");
} else {
System.out.println("obj is still alive");
}
System.out.println("第2次gc");
obj = null;
System.gc();
// 因为Finalizer线程优先级很低,暂停2秒,以等待它
Thread.sleep(2000);
if (obj == null) {
System.out.println("obj is dead");
} else {
System.out.println("obj is still alive");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
第1次gc
obj is still alive
第2次gc
obj is dead
04 注意
Finalizer线程去执行它们的finalize() , 这里所说的“执行”是指虚拟机会触发这个方法开始运行, 但并不承诺一定会等待它运行结束。 这样做的原因是, 如果某个对象finalize()方法执行缓慢, 或更极端地发生了死循环, 很可能导致F-Queue队列中的其他对象永久处于等待, 甚至导致整个内存回收子系统的崩溃
版权声明:本文为qq_37335180原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。