Java对象什么时候死亡、finalize()方法的执行过程

一. 问题背景

遇到一个面试题“GC的两种判定方法(如何判断一个对象是否存活?)”,其中涉及引用计数法和可达性算法,而当一个对象经过可达性分析,会涉及两次标记,其中又涉及finalize()。因此今天了解一下Java对象什么时候死亡以及finalize()方法的执行过程。

此笔记仅供自己参考,如有错误请指正

参考自:JAVA中对象什么时候死亡以及什么时候执行finalize()方法

二. 储备知识

2.1 引用

jdk1.2后,Java将引用分为强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)

2.1.1 强引用Strong Reference

类似Object obj = new Object();这类引用,只要引用还在,垃圾收集器就不会回收掉被引用的对象(即new出来的Object)

2.1.2 软引用Soft Reference

在抛出内存溢出异常之前,会把软引用引用的对象列入回收范围之中进行第二次回收。如果这次回收还没有足够的内存,才会抛出内存溢出异常。

总结:经过一次垃圾回收后,若还是内存不足,则回收掉软引用关联的对象

2.1.3 弱引用Weak Reference

只要进行垃圾回收,就会回收掉引用关联的对象

2.1.4 虚引用Phantom Reference

不会对生存时间构成影响,唯一目的是对象被回收时收到一个系统通知

2.2 可达性算法(引用链法)

从一个被称为GC Root的对象开始向下搜索,一个对象到GC Root没有任何引用链相连时,则说明此对象不可用。

2.3 哪些对象可以作为GC Root

  • 虚拟机栈中引用的对象(是对象,不是引用)
  • 方法区静态属性引用的对象
  • 方法区常量池引用的对象
  • 本地方法栈JNI引用的对象

2.4 finalize()相关的知识

2.4.1 finalize()来自哪里

finalize()是Object类里面的方法,而每一个对象都是Object类的子类,因此每一个对象都有finalize()方法(自继承得来的)。

2.4.2 finalize()的作用

用来关闭某些资源(比如数据库连接,IO流等等)。用法是重写finalize()方法即可(在方法体里面进行关闭数据库连接,关闭IO流等等)。

三. 对象的复活(对象什么时候死亡)以及finalize()的执行过程

  • 即使对象在可达性算法中被判为不可达,但并非是真正死了,此时它们处于“缓刑阶段”。要真正死亡需要经理2次标记过程。

  • 如果对象经过可达性分析后没有与GC Root相连的引用链,那么它将被第一次标记 并 进行一次筛选

  • 筛选的条件是:是否有必要执行finalize()方法

  • 当对象没有覆盖finalize()方法 或 finalize()方法已经被虚拟机调用过,虚拟机将这2中情况视为“没有必要执行

  • 如果对象被判定为有必要执行finalize()方法,那么此对象将被加入到一个叫F-Queue的队列之中,并且稍后由一个虚拟机自行创建的低优先级FinalizeHandler线程执行它

  • 这里的执行是指虚拟机触发这个方法,但不承诺会等待它运行结束。这样做的原因是如果一个对象在finalize()方法中执行缓慢,或者发生死循环,将很可能导致F-Queue队列中其他对象永久处于等待,甚至导致整个内存回收系统崩溃。

  • finalize()方法是对象逃脱死亡的最后一次机会。稍后GC将对F-Queue的对象进行第二次小规模的标记。如果对象要在finalize()方法中拯救自己——只需重新与引用链上的任何一个对象建立关联即可。譬如把自己赋值给类变量或者对象的成员变量,那么在第二次标记时(GC会对F-Queue队列中的对象进行第二次标记)它将被移除出“即将回收”的集合。如果对象此时还没有逃脱,那么基本上它就真的被回收了。

总结:finalize并不是一定要执行,它只能执行1次或0次。如果它能在finalize()中建立对象关联,则当前对象可以复活一次。

过程如下图:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值