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

相关文章

Oracle 通过 ROWID 批量更新表的方法

《Oracle通过ROWID批量更新表的方法》在Oracle数据库中,使用ROWID进行批量更新是一种高效的更新方法,因为它直接定位到物理行位置,避免了通过索引查找的开销,下面给大家介绍Orac... 目录oracle 通过 ROWID 批量更新表ROWID 基本概念性能优化建议性能UoTrFPH优化建议注

Pandas进行周期与时间戳转换的方法

《Pandas进行周期与时间戳转换的方法》本教程将深入讲解如何在pandas中使用to_period()和to_timestamp()方法,完成时间戳与周期之间的转换,并结合实际应用场景展示这些方法的... 目录to_period() 时间戳转周期基本操作应用示例to_timestamp() 周期转时间戳基

在 PyQt 加载 UI 三种常见方法

《在PyQt加载UI三种常见方法》在PyQt中,加载UI文件通常指的是使用QtDesigner设计的.ui文件,并将其转换为Python代码,以便在PyQt应用程序中使用,这篇文章给大家介绍在... 目录方法一:使用 uic 模块动态加载 (不推荐用于大型项目)方法二:将 UI 文件编译为 python 模

C++类和对象之初始化列表的使用方式

《C++类和对象之初始化列表的使用方式》:本文主要介绍C++类和对象之初始化列表的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C++初始化列表详解:性能优化与正确实践什么是初始化列表?初始化列表的三大核心作用1. 性能优化:避免不必要的赋值操作2. 强

Python将字库文件打包成可执行文件的常见方法

《Python将字库文件打包成可执行文件的常见方法》在Python打包时,如果你想将字库文件一起打包成一个可执行文件,有几种常见的方法,具体取决于你使用的打包工具,下面就跟随小编一起了解下具体的实现方... 目录使用 PyInstaller基本方法 - 使用 --add-data 参数使用 spec 文件(

Python的pip在命令行无法使用问题的解决方法

《Python的pip在命令行无法使用问题的解决方法》PIP是通用的Python包管理工具,提供了对Python包的查找、下载、安装、卸载、更新等功能,安装诸如Pygame、Pymysql等Pyt... 目录前言一. pip是什么?二. 为什么无法使用?1. 当我们在命令行输入指令并回车时,一般主要是出现以

通过C#获取Excel单元格的数据类型的方法详解

《通过C#获取Excel单元格的数据类型的方法详解》在处理Excel文件时,了解单元格的数据类型有助于我们正确地解析和处理数据,本文将详细介绍如何使用FreeSpire.XLS来获取Excel单元格的... 目录引言环境配置6种常见数据类型C# 读取单元格数据类型引言在处理 Excel 文件时,了解单元格

MySQL连接池(Pool)常用方法详解

《MySQL连接池(Pool)常用方法详解》本文详细介绍了MySQL连接池的常用方法,包括创建连接池、核心方法连接对象的方法、连接池管理方法以及事务处理,同时,还提供了最佳实践和性能提示,帮助开发者构... 目录mysql 连接池 (Pool) 常用方法详解1. 创建连接池2. 核心方法2.1 pool.q

Spring Boot Controller处理HTTP请求体的方法

《SpringBootController处理HTTP请求体的方法》SpringBoot提供了强大的机制来处理不同Content-Type​的HTTP请求体,这主要依赖于HttpMessageCo... 目录一、核心机制:HttpMessageConverter​二、按Content-Type​处理详解1.

查看MySQL数据库版本的四种方法

《查看MySQL数据库版本的四种方法》查看MySQL数据库的版本信息可以通过多种方法实现,包括使用命令行工具、SQL查询语句和图形化管理工具等,以下是详细的步骤和示例代码,需要的朋友可以参考下... 目录方法一:使用命令行工具1. 使用 mysql 命令示例:方法二:使用 mysqladmin 命令示例:方