谈谈你对 finalize 方法的理解,该怎样回答才能体现出高水平?浮于表面的答案永远不行!

本文主要是介绍谈谈你对 finalize 方法的理解,该怎样回答才能体现出高水平?浮于表面的答案永远不行!,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

1. finalize 方法是什么?

2. finalize 方法的作用?

3. 为什么强烈不建议在 finalize 方法中进行资源的释放和清理工作


1. finalize 方法是什么?

首先要知道,finalize 方法是 Object 类中的一个方法,从源码中叶可儿一看到,所以所有的对象都会具有这个方法,该方法修饰符为 protected ,子类可以进行 @Override 重写,但实际开发过程中一般不会去理会它。

在 JDK9 之后,该方法已经被官方不推荐使用了,但面试的时候还是有可能会被问到的,所以我们就来聊聊该方法的一些作用。

2. finalize 方法的作用?

finalize 方法是在对象被垃圾回收器回收之前执行的,当我们将一个对象设置为 null 之后,它就变成了垃圾,等待着垃圾回收器回收,finalize 方法主要就是做一些清理善后的工作,如果一个对象重写了 finalize 方法,那么它在被垃圾回收器回收之前,就会先执行 finalize 方法。

由此也带来了它的另一个作用,通常一个对象都是具有很多的功能属性的,所以我们就可以将一些资源的释放;例如文件关闭操作,网络连接断开操作放到 finalize 方法中去完成。

如下代码所示

public class Test {// 重写 Test 类中的 finalize() 方法@Overridepublic void finalize() throws Throwable{// 打印一句话作为标记,证明该方法被调用过System.out.println("finalize方法执行");}public static void main(String[] args) throws Exception {// 创建类对象 tTest t = new Test();
// 获取该对象System.out.println(t+"第一次获取对象");
// 将对象t赋值为 null,此时堆中的对象就会变成垃圾t = null;// 手动开启垃圾回收GC,将垃圾回收,验证 finalize方法是否执行System.gc();// 因为GC垃圾回收是另外的垃圾回收线程,所以我们让主线程先睡两秒,避免造成误差Thread.sleep(2000);// 经过GC之后再次获取t对象System.out.println(t+"第二次获取对象");}
}

这里还有一点需要提醒注意,Java虚拟机的GC是单独的GC垃圾回收线程,并且该线程是 main 线程的守护线程,只要 main 线程运行结束,GC垃圾回收线程就会停止,所以在代码中我才让 main 线程调用 sleep 方法。

然后我们运行上述方法,在控制台中得到如下所示结果

可以看到,将对象 t 赋值为 null 之后,finalize 方法就执行了。

3. 为什么强烈不建议在 finalize 方法中进行资源的释放和清理工作

经过了上面的演示,现在已经得知,finalize 方法会在对象被垃圾回收器回收之前执行此方法,但是!!!强烈不建议在 finalize 方法中进行资源的释放和清理工作。

原因我总结了以下三点

(1)资源释放实际成谜。

如果我们重写了 finalize 方法,那么对象在变成垃圾被垃圾回收器回收之前,需要先执行 finalize 方法,而 finalize 方法并不是由垃圾回收器来调用的,是有一个专门的线程叫 finalizer 来调用的,finalizer 线程内部有一个引用队列,垃圾回收器识别到垃圾对象之后,会把该对象添加到引用队列中去,finalizer 线程会依次调用每个对象的 finalize 方法然后进行清理。如果说一个对象不再被任何一个变量引用,我们就希望它能够马上被回收释放占用的系统资源,但是垃圾回收算法的运行时机是不确定的,而且缺少对该垃圾对象的监控,所以我们无从得知盖拉几何时会被清理掉,资源的释放时机就成了谜。

(2)资源释放异常,对象变成"僵尸"。

finalize 既然是一个方法,那么它就有可能抛出异常,如果抛出异常,垃圾清理到一半又没有清理完,此时这个对象就不能被清除掉,就变成半死不活的"僵尸"了,一直占用系统资源无法被释放。

(3)很容易导致OOM(内存溢出)

GC垃圾回收线程和主程序的线程不是同一个线程。也就是说,我们的主线程,也可以说是业务一直都在持续地进行着,那么业务就很有可能会在内存中继续创建出新的对象进行其他的业务操作。而此时先前创建的对象被回收需要调用 finalize 方法,如果我们将一些资源的释放工作和内存清理工作全部放到 finalize 方法中的话,是非常耗时的,特别是网络断开连接操作,需要等待对方的响应才能断开连接,但现在内存中的垃圾对象又需要等待 finalize 方法执行完毕后才能清除,由于业务的不断进行,还有不断新的对象被创建,垃圾对象的清理速度慢,新对象的创建速度快,清理的速度没有创建的速度快,一定会造成内存溢出。

这篇关于谈谈你对 finalize 方法的理解,该怎样回答才能体现出高水平?浮于表面的答案永远不行!的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

深入理解Apache Kafka(分布式流处理平台)

《深入理解ApacheKafka(分布式流处理平台)》ApacheKafka作为现代分布式系统中的核心中间件,为构建高吞吐量、低延迟的数据管道提供了强大支持,本文将深入探讨Kafka的核心概念、架构... 目录引言一、Apache Kafka概述1.1 什么是Kafka?1.2 Kafka的核心概念二、Ka

Python中的魔术方法__new__详解

《Python中的魔术方法__new__详解》:本文主要介绍Python中的魔术方法__new__的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、核心意义与机制1.1 构造过程原理1.2 与 __init__ 对比二、核心功能解析2.1 核心能力2.2

Python Transformer 库安装配置及使用方法

《PythonTransformer库安装配置及使用方法》HuggingFaceTransformers是自然语言处理(NLP)领域最流行的开源库之一,支持基于Transformer架构的预训练模... 目录python 中的 Transformer 库及使用方法一、库的概述二、安装与配置三、基础使用:Pi

关于pandas的read_csv方法使用解读

《关于pandas的read_csv方法使用解读》:本文主要介绍关于pandas的read_csv方法使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录pandas的read_csv方法解读read_csv中的参数基本参数通用解析参数空值处理相关参数时间处理相关

前端下载文件时如何后端返回的文件流一些常见方法

《前端下载文件时如何后端返回的文件流一些常见方法》:本文主要介绍前端下载文件时如何后端返回的文件流一些常见方法,包括使用Blob和URL.createObjectURL创建下载链接,以及处理带有C... 目录1. 使用 Blob 和 URL.createObjectURL 创建下载链接例子:使用 Blob

Java中使用Hutool进行AES加密解密的方法举例

《Java中使用Hutool进行AES加密解密的方法举例》AES是一种对称加密,所谓对称加密就是加密与解密使用的秘钥是一个,下面:本文主要介绍Java中使用Hutool进行AES加密解密的相关资料... 目录前言一、Hutool简介与引入1.1 Hutool简介1.2 引入Hutool二、AES加密解密基础

Pytest多环境切换的常见方法介绍

《Pytest多环境切换的常见方法介绍》Pytest作为自动化测试的主力框架,如何实现本地、测试、预发、生产环境的灵活切换,本文总结了通过pytest框架实现自由环境切换的几种方法,大家可以根据需要进... 目录1.pytest-base-url2.hooks函数3.yml和fixture结论你是否也遇到过

鸿蒙中Axios数据请求的封装和配置方法

《鸿蒙中Axios数据请求的封装和配置方法》:本文主要介绍鸿蒙中Axios数据请求的封装和配置方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1.配置权限 应用级权限和系统级权限2.配置网络请求的代码3.下载在Entry中 下载AxIOS4.封装Htt

Redis实现延迟任务的三种方法详解

《Redis实现延迟任务的三种方法详解》延迟任务(DelayedTask)是指在未来的某个时间点,执行相应的任务,本文为大家整理了三种常见的实现方法,感兴趣的小伙伴可以参考一下... 目录1.前言2.Redis如何实现延迟任务3.代码实现3.1. 过期键通知事件实现3.2. 使用ZSet实现延迟任务3.3

idea maven编译报错Java heap space的解决方法

《ideamaven编译报错Javaheapspace的解决方法》这篇文章主要为大家详细介绍了ideamaven编译报错Javaheapspace的相关解决方法,文中的示例代码讲解详细,感兴趣的... 目录1.增加 Maven 编译的堆内存2. 增加 IntelliJ IDEA 的堆内存3. 优化 Mave