Finalize 与 GC

预备知识

  • Java的Gc只负责内存的清理,其它方面的清理要程序员手工操作
  • 调用Gc并不能保证Gc一定会执行,因为GC的线程优先级比较低,所以在测试的时候调用完GC一般使当前线程睡眠以便GC线程的执行。
  • 用户自己调用finalize函数并不会影响到清理,和调用一个正常的方法一样,没有什么特别的影响
  • jvm保证一个对象占用的内存回收之前,如果这个对象的类实现了finalize方法,一定会执行且仅执行一次,至于如何保证的会在下面讲到
  • 对象的finalize链需要手工构造,也就是如果重写finalize函数需要手动调用super.finalize()

对象的销毁过程

没有重写finalize方法

  • 刚创建的对象状态是reachable,如果对象变成不可达,GC会直接将对象销毁

重写了finalize方法

  • 刚创建:reachable + unfinalized状态,意思是:该对象可达,而且该对象的finalize函数还没有被调用,并且没有准备被调用,因为该对象可达GC不会试图去销毁该对象。
  • 对象的引用没有了,现在是不可达状态,但是因为其重写了finalize函数,所以jvm会将该对象放到F-queue中,该队列中的对象状态都变成:F-reachable + finalizable,意思是:该对象通过F-queue可达而且准备被调用finalize函数。
  • 在任何时候,如果F-queue队列非空,GC的一个线程都会从该队列中取出一个对象,将其状态标记为:unreachable + finablized,并执行它的finalize函数, 意思是:该对象现在不可达,而且已经执行过finalize函数,不能再次被放到F-queue队列中,也就保证了finalize只会被执行一次。
  • 如果F-queue中的一个对象在其finalize函数中“复活了自己”---将自己的引用又赋值给了一个变量,这个时候这个对象就再次变成了reachable,但是他的finalize函数仍然不会被再次执行,也就是说它现在的状态类似于一个没有覆盖finalize函数的对象,如果再次变得不可达,会直接被GC销毁。
  • 下面演示一个对象在finalize函数中复活自己的例子:
public class Main{
    static Main HOOK;

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("finalize function is called");
        HOOK=this;
    }

    public static void main(String[] args) throws InterruptedException {
        HOOK = new Main();
        HOOK=null;
        System.gc();
        Thread.sleep(3000);
        if(HOOK==null){
            System.out.println("object is dead");
        }else {
            System.out.println("object is alive");
        }

        HOOK=null;
        System.gc();
        Thread.sleep(3000);
        if(HOOK==null){
            System.out.println("object is dead");
        }else {
            System.out.println("object is alive");
        }
    }
}
  • output:
finalize function is called
object is alive
object is dead
  • GC第一次执行的时候,调用了finalize函数,通过将this引用赋值给另一个变量,将对象复活,所以对象仍然是存活的,但是第二次就不会在调用finalize函数,所以对象被销毁。

 

 

来源:简书
链接:https://www.jianshu.com/p/68f46c022f20
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值