finalize()
注:本文的目的并不是鼓励使用finalize方法,而是大致理清其作用、问题以及GC执行finalize的过程。
1. finalize的作用
- finalize()是Object的protected方法,子类可以覆盖该方法以实现资源清理工作,GC在回收对象之前调用该方法。
- finalize()与C++中的析构函数不是对应的。C++中的析构函数调用的时机是确定的(对象离开作用域或delete掉),但Java中的finalize的调用具有不确定性
- 不建议用finalize方法完成“非内存资源”的清理工作,但建议用于:① 清理本地对象(通过JNI创建的对象);② 作为确保某些非内存资源(如Socket、文件等)释放的一个补充:在finalize方法中显式调用其他资源释放方法。其原因可见下文[finalize的问题]
2. finalize的问题
- 一些与finalize相关的方法,由于一些致命的缺陷,已经被废弃了,如System.runFinalizersOnExit()方法、Runtime.runFinalizersOnExit()方法
- System.gc()与System.runFinalization()方法增加了finalize方法执行的机会,但不可盲目依赖它们
- Java语言规范并不保证finalize方法会被及时地执行、而且根本不会保证它们会被执行
- finalize方法可能会带来性能问题。因为JVM通常在单独的低优先级线程中完成finalize的执行
- 对象再生问题:finalize方法中,可将待回收对象赋值给GC Roots可达的对象引用,从而达到对象再生的目的
- finalize方法至多由GC执行一次(用户当然可以手动调用对象的finalize方法,但并不影响GC对finalize的行为)
3. finalize的执行过程(生命周期)
- unfinalized: 新建对象会先进入此状态,GC并未准备执行其finalize方法,因为该对象是可达的
- finalizable: 表示GC可对该对象执行finalize方法,GC已检测到该对象不可达。正如前面所述,GC通过F-Queue队列和一专用线程完成finalize的执行
- finalized: 表示GC已经对该对象执行过finalize方法
- reachable: 表示GC Roots引用可达
- finalizer-reachable(f-reachable):表示不是reachable,但可通过某个finalizable对象可达
- unreachable:对象不可通过上面两种途径可达
![](/assets/blank.gif)
- 新建对象首先处于[reachable, unfinalized]状态(A)
- 随着程序的运行,一些引用关系会消失,导致状态变迁,从reachable状态变迁到f-reachable(B, C, D)或unreachable(E, F)状态
- 若JVM检测到处于unfinalized状态的对象变成f-reachable或unreachable,JVM会将其标记为finalizable状态(G,H)。若对象原处于[unreachable, unfinalized]状态,则同时将其标记为f-reachable(H)。
- 在某个时刻,JVM取出某个finalizable对象,将其标记为finalized并在某个线程中执行其finalize方法。由于是在活动线程中引用了该对象,该对象将变迁到(reachable, finalized)状态(K或J)。该动作将影响某些其他对象从f-reachable状态重新回到reachable状态(L, M, N)
- 处于finalizable状态的对象不能同时是unreahable的,由第4点可知,将对象finalizable对象标记为finalized时会由某个线程执行该对象的finalize方法,致使其变成reachable。这也是图中只有八个状态点的原因
- 程序员手动调用finalize方法并不会影响到上述内部标记的变化,因此JVM只会至多调用finalize一次,即使该对象“复活”也是如此。程序员手动调用多少次不影响JVM的行为
- 若JVM检测到finalized状态的对象变成unreachable,回收其内存(I)
- 若对象并未覆盖finalize方法,JVM会进行优化,直接回收对象(O)
- 注:System.runFinalizersOnExit()等方法可以使对象即使处于reachable状态,JVM仍对其执行finalize方法
4. 一些代码示例
(1) 对象复活
- public class GC {
- public static GC SAVE_HOOK = null;
- public static void main(String[] args) throws InterruptedException {
- SAVE_HOOK = new GC();
- SAVE_HOOK = null;
- System.gc();
- Thread.sleep(500);
- if (null != SAVE_HOOK) { //此时对象应该处于(reachable, finalized)状态
- System.out.println(”Yes , I am still alive”);
- } else {
- System.out.println(”No , I am dead”);
- }
- SAVE_HOOK = null;
- System.gc();
- Thread.sleep(500);
- if (null != SAVE_HOOK) {
- System.out.println(”Yes , I am still alive”);
- } else {
- System.out.println(”No , I am dead”);
- }
- }
- @Override
- protected void finalize() throws Throwable {
- super.finalize();
- System.out.println(”execute method finalize()”);
- SAVE_HOOK = this;
- }
- }
(2)覆盖finalize方法以确保资源释放
作为一个补充操作,以防用户忘记“关闭“资源,JDK中FileInputStream、FileOutputStream、Connection类均用了此”技术“,下面代码摘自FileInputStream类
- /**
- * Ensures that the <code>close</code> method of this file input stream is
- * called when there are no more references to it.
- *
- * @exception IOException if an I/O error occurs.
- * @see java.io.FileInputStream#close()
- */
- protected void finalize() throws IOException {
- if ((fd != null) && (fd != FileDescriptor.in)) {
- /* if fd is shared, the references in FileDescriptor
- * will ensure that finalizer is only called when
- * safe to do so. All references using the fd have
- * become unreachable. We can call close()
- */
- close();
- }
- }
参考:
12.6 Finalization of Class Instances https://notendur.hi.is//~snorri/SDK-docs/lang/lang083.htm深入理解java的finalize http://zhang-xzhi-xjtu.iteye.com/blog/484934The Finalizable Object http://www.artima.com/interfacedesign/Finalizable.html
finalize()相关推荐
- Object的finalize()方法的作用是否与C++的析构函数作用相同
Object的finalize()方法的作用是否与C++的析构函数作用相同 public class Finalization {private static Finalization finaliz ...
- java object finalize_Java Object finalize() 方法
Object finalize() 方法用于实例被垃圾回收器回收的时触发的操作. 当 GC (垃圾回收器) 确定不存在对该对象的有更多引用时,对象的垃圾回收器就会调用这个方法. 语法 protecte ...
- Finalize/Dispose/Destructor
我总是会搞混这些东西,还是写下来帮助记忆. Finalize 即Object.Finalize(),C#中不允许使用Finalize,析构器就等价于Finalize. Destructor 析构器(D ...
- .net内存回收与Dispose﹐Close﹐Finalize方法
.net内存回收与Dispose﹐Close﹐Finalize方法 一. net的对象使用一般分为三种情况﹕ 1.创建对象 2.使用对象 3.释放对象 二.创建对象 1.创建对象实际分为两个步骤﹕变量 ...
- 3.1、final、finally、 finalize
final 可以用来修饰类.方法.变量,分别有不同的意义,final 修饰的 class 代表不可以继承扩展,final 的变量是不可以修改的,而 final 的方法也是不可以重写的(override ...
- final finally finalize 的区别
1.final final修饰类,说明这个类不能被继承,是以个顶级类. final修饰变量,说明这个变量是常量. final修饰方法,表示这个方法不能被重写,不过可以冲在final方法. 比如有个基类 ...
- 对于一些手机内存概念的思考、深入理解java的finalize,对于内存优化的小总结...
2019独角兽企业重金招聘Python工程师标准>>> 最近在对手机性能做了一些小概念总结,方便对于自己的个人思考 Shallow Size: 对象本身占用的内存空间,不包含其引用的 ...
- final,finally,finalize的区别
1.final 修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承.因此一个类不能既被声明为 abstract的,又被声明为final的.将变量或方法声明为 ...
- Java将弃用finalize()方法?
最近,OpenJDK邮件组core-libs-dev里出现了一封邮件,建议弃用Object类的finalize()方法. \\ 弃用Object类的方法将会是一件非常不寻常的事情.Java从 1.0开 ...
- java final 变量 回收_java入门教程-Java中final,finally,finalize三个关键字的区别
final 当这个关键字修饰一个类时,意味着他不能派生出新的子类,也就是说不能被继承,因此一个类不能被同时声明为abstract和final.当final修饰变量或者方法时,可以保证他们在使用中不会被 ...
最新文章
- 网站位置服务器,如何查看网站的服务器位置
- linux fork, system, exec()
- 解决IntelliJ IDEA下Maven报错Unknown lifecycle phase “.test.skip=true“. You must specify a valid lifecycle
- 消息中间件系列(八):Kafka、RocketMQ、RabbitMQ等的优劣势比较
- § Transitive Intransitive Verb
- ROP_return to dl-resolve学习笔记
- 算法笔记:二叉树的序列化和反序列化(剑指 Offer 37)
- 深度学习框架间互操作的工具:MMdnn
- paip.-Djava.library.path -Djava.ext.dirs= 的区别
- excel mac 水晶球_水晶球软件使用crystalball.pptx
- 量化小科普【什么是量化?常用的股票量化指标、如何搭建量化交易系统】
- 图像处理中关于矩的解释
- 如何度量两幅图像的相似度--结构相似度 SSIM 原理及代码
- OpenCV训练分类器制作xml文档
- win 7硬盘安装centos7 亲测可行
- 一个文本回射C/S程序并讨论:fork、信号处理机制、僵死进程处理
- 2020/5/4/ 每日一咕
- 【技术美术图形部分】图形渲染管线2.0-GPU管线概述几何阶段
- 1.微信好友定时发送信息
- Google英文word2vec预训练模型 word2vec-GoogleNews-vectors
热门文章
- 在Remix中运行合约JS脚本
- “就业”or“创业”,大学生毕业如何选择,校园市场是新出路?
- 开源创新 协同融合|2023 开放原子全球开源峰会开源协作平台分论坛即将启幕
- ESP32系列--第十篇 ADC电阻网络按键
- ZOJ3775:?(_o)!
- android fastboot模式,Fastboot是什么意思 fastboot模式怎么进入?
- winform c# 获取电脑配置信息和cpu 内存使用率
- AI音乐创作,让每一个人都成为音乐家
- systemdd-dev病毒杀
- 麻将胡牌算法(遍历+剪枝)