finalize()及垃圾回收

整体认识

finalize()方法是一个与垃圾回收相关的方法(和C++中的析构函数有很大的区别),

finalize()方法不是用于垃圾回收,而是与垃圾回收相关

是Objecte类中的方法

finalize()方法的说明方式 : protected void finalize()throws Throwable

一个对象只能调用一次finalize()方法

深入认识finalize()

想要深入了解finalize()方法就要先对Jvm的堆内存的垃圾回收机制有一个认识;

JVM采用垃圾回收算法是可达性分析算法,下面先了解一下可达性算法:

可达性算法可用用下面的一个树形图来认识,若内存与GC root有连接则该内存是不可被回收的,若相应的内存与GC root没有连接的通路那么该内存就是可回收的(但不一定被回收)

 

 

a  b  c 与GC root有连接的通路,所以他们三个都是不可回收的,而d e与GC Roots没有通路相连,所以他们是可被回收的,当然GC Roots的选取是有要求的

可作为GC Roots的对象:

1、 虚拟机栈(java 方法)中引用的对象

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

3、 方法区中常量引用的对象

4、 native方法(本地方法栈)中引用的对象

上面我们说到若没有与GC Roots相连的对象是可回收的,但是并不是就一定可以被回收,java中对象要被回收至少要经历两次标记过程:

第一次标记:若对象没有与GC Roots相连接则被第一次标记

第二次标记:这次标记需要分情况讨论

        第一种情况:若该对象的类覆盖了finalize()方法,并且该对象没有调用过finalize()方法,则虚拟机将会把该对象存入到一个叫做F-Queue队列中,等到一定的时间虚拟机将会自己创建一个低优先级的线程(Finalizer),由该线程去触发finalize()方法,若finalize()方法中将此对象与还在与GC Roots相连的对象相关联,那么该对象就不会被回收,否则该对象就会被回收

        第二种情况:finalize()方法已经被调用,或者没有覆盖finalize()方法。这种情况就不会将对象放进F-Queue队列,也不会调用finalize()方法,而是对对象进行第二次标记,回收对象

总结

通过上面的描述知道一个与GC Roots没有连接通道的对象要想不被回收就只有在finalize()方法中将该对象与GC Roots建立联系,仿佛并不是垃圾回收而是自救的一个通道,所以finalize()方法不是用于垃圾回收,而是与垃圾回收相关,除了上述作用外,还有一个作用

当该对象不进行自救时,在finalize()方法中执行该对象必须要执行的代码(因为该对象马上就要被回收),例如释放资源,这与try finally中finally的作用是一样的,并且finally可以做的更好,

posted on 2019-03-30 22:55  努力学习的菜鸡  阅读(522)  评论(0编辑  收藏  举报

导航