56.对象的finalization机制、finalize方法理解

2024-05-29 16:38

本文主要是介绍56.对象的finalization机制、finalize方法理解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 1.对象的`finalization`机制

1.对象的finalization机制

  1. Java提供了finalization机制来允许开发人员提供对象销毁之前自定义处理逻辑。
  2. 垃圾回收一个对象之前,总会先调用这个对象的finalize()方法
  3. finalize()方法是Object类中定义的,允许在任何子类中被重写,用于对象被回收时进行资源释放,例如,关闭数据库连接等等。
    在这里插入图片描述
  4. 不要主动的调用finalize()方法,应该交给垃圾回收机制来调用。
    原因:
    a)finalize()可能导致对象复活
    b)finalize()执行时间没有保障,完全有GC线程决定,极端情况下,若不发生GCfinalize()就不会被调用
    c)糟糕的finalize()会影响GC的性能
    在这里插入图片描述
  5. JVM中的对象可能出现的3种状态。
    a)可触及的:从根节点开始,可以到达这个对象
    b)可复活的:对象的所有引用都被释放,但是对象可能在finalize()被复活(例如:在finalize()中又有新的引用指向该对象)。
    c)不可触及的,对象的finalize()被调用之后,对象没有复活,那么会进入不可触及的状态。不可触及的对象不可能被复活,因为finalize()只会调用一次

只有不可触及的对象才能够被回收。
在这里插入图片描述
判断一个对象是否可以被回收:

  1. 如果objAGC Roots没有引用链,则进行第一次标记。(这里的标记意思是,对象是不可达的,对象可能是可复活的或者不可触及的。)
  2. 进行筛选,判断对象是否需要执行finalize()方法
    1)如果对象objA没有重写finalize()方法,或者finalize()方法已经被虚拟机调用过,则虚拟机认为“没有必要执行finalize()”,objA被判定为不可触及的
    2)如果objA重写了finalize()方法,且还未执行过,那么objA会被插入到F-Queue队列中,由一个虚拟机自动创建的、低优先级的Finalizer线程触发其finalize()方法。
    3) finalize()方法是对象逃脱死亡的最后机会,稍后GC会对F-Queue中的objA对象进行第二次标记,如果objAfinalize()方法中与引用链上的任何一个对象建立了联系(也就是复活了),那么第二次标记时,objA会被移出“即将回收”集合。之后,对象会再次出现没有引用存在的情况,在这个情况下,finalize()方法不会被再次调用,对象会直接变成不可触及状态。因为,一个对象的finalize()方法只会被调用一次。
    在这里插入图片描述
    演示对象的finalization机制的例子:
/*** 测试Object类中finalize()方法,即对象的finalization机制。*/
public class CanReliveObj {public static CanReliveObj obj;//类变量,属于 GC Root//finalize方法只能被调用一次@Overrideprotected void finalize() throws Throwable {super.finalize();System.out.println("调用当前类重写的finalize()方法");obj = this;//当前待回收的对象在finalize()方法中与引用链上的一个对象obj建立了联系。 obj是GC Roots,this是当前对象,也就是要被回收的对象。}public static void main(String[] args) {try {obj = new CanReliveObj();// 对象第一次成功拯救自己obj = null;System.gc();//调用垃圾回收器。第一次GC的时候,会执行finalize方法,在finalize方法中,由于obj指向了this,obj变量是一个GC Root,要被回收的对象与引用链上的对象建立了又联系,所以对象被复活了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(); // 第二次调用GC,由于finalize只能被调用一次,所以对象会直接被回收// 因为Finalizer线程优先级很低,暂停2秒,以等待它Thread.sleep(2000);if (obj == null) {System.out.println("obj is dead"); // 这句会输出} else {System.out.println("obj is still alive");}} catch (InterruptedException e) {e.printStackTrace();}}
}

更多JVM文章请访问我的JVM专栏:
https://blog.csdn.net/u011069294/category_10113093.html

这篇关于56.对象的finalization机制、finalize方法理解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1014065

相关文章

python获取指定名字的程序的文件路径的两种方法

《python获取指定名字的程序的文件路径的两种方法》本文主要介绍了python获取指定名字的程序的文件路径的两种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 最近在做项目,需要用到给定一个程序名字就可以自动获取到这个程序在Windows系统下的绝对路径,以下

JavaScript中的高级调试方法全攻略指南

《JavaScript中的高级调试方法全攻略指南》什么是高级JavaScript调试技巧,它比console.log有何优势,如何使用断点调试定位问题,通过本文,我们将深入解答这些问题,带您从理论到实... 目录观点与案例结合观点1观点2观点3观点4观点5高级调试技巧详解实战案例断点调试:定位变量错误性能分

Python中 try / except / else / finally 异常处理方法详解

《Python中try/except/else/finally异常处理方法详解》:本文主要介绍Python中try/except/else/finally异常处理方法的相关资料,涵... 目录1. 基本结构2. 各部分的作用tryexceptelsefinally3. 执行流程总结4. 常见用法(1)多个e

JavaScript中比较两个数组是否有相同元素(交集)的三种常用方法

《JavaScript中比较两个数组是否有相同元素(交集)的三种常用方法》:本文主要介绍JavaScript中比较两个数组是否有相同元素(交集)的三种常用方法,每种方法结合实例代码给大家介绍的非常... 目录引言:为什么"相等"判断如此重要?方法1:使用some()+includes()(适合小数组)方法2

504 Gateway Timeout网关超时的根源及完美解决方法

《504GatewayTimeout网关超时的根源及完美解决方法》在日常开发和运维过程中,504GatewayTimeout错误是常见的网络问题之一,尤其是在使用反向代理(如Nginx)或... 目录引言为什么会出现 504 错误?1. 探索 504 Gateway Timeout 错误的根源 1.1 后端

MySQL 表空却 ibd 文件过大的问题及解决方法

《MySQL表空却ibd文件过大的问题及解决方法》本文给大家介绍MySQL表空却ibd文件过大的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录一、问题背景:表空却 “吃满” 磁盘的怪事二、问题复现:一步步编程还原异常场景1. 准备测试源表与数据

基于Redis自动过期的流处理暂停机制

《基于Redis自动过期的流处理暂停机制》基于Redis自动过期的流处理暂停机制是一种高效、可靠且易于实现的解决方案,防止延时过大的数据影响实时处理自动恢复处理,以避免积压的数据影响实时性,下面就来详... 目录核心思路代码实现1. 初始化Redis连接和键前缀2. 接收数据时检查暂停状态3. 检测到延时过

python 线程池顺序执行的方法实现

《python线程池顺序执行的方法实现》在Python中,线程池默认是并发执行任务的,但若需要实现任务的顺序执行,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋... 目录方案一:强制单线程(伪顺序执行)方案二:按提交顺序获取结果方案三:任务间依赖控制方案四:队列顺序消

SpringBoot通过main方法启动web项目实践

《SpringBoot通过main方法启动web项目实践》SpringBoot通过SpringApplication.run()启动Web项目,自动推断应用类型,加载初始化器与监听器,配置Spring... 目录1. 启动入口:SpringApplication.run()2. SpringApplicat

Redis中哨兵机制和集群的区别及说明

《Redis中哨兵机制和集群的区别及说明》Redis哨兵通过主从复制实现高可用,适用于中小规模数据;集群采用分布式分片,支持动态扩展,适合大规模数据,哨兵管理简单但扩展性弱,集群性能更强但架构复杂,根... 目录一、架构设计与节点角色1. 哨兵机制(Sentinel)2. 集群(Cluster)二、数据分片