注:本文的目的并不是鼓励使用finalize方法,而是大致理清其作用、问题以及GC执行finalize的过程。

1. finalize的作用

2. finalize的问题

3. finalize的执行过程(生命周期)

(1) 首先,大致描述一下finalize流程:当对象变成(GC Roots)不可达时,GC会判断该对象是否覆盖了finalize方法,若未覆盖,则直接将其回收。否则,若对象未执行过finalize方法,将其放入F-Queue队列,由一低优先级线程执行该队列中对象的finalize方法。执行finalize方法完毕后,GC会再次判断该对象是否可达,若不可达,则进行回收,否则,对象“复活”。
(2) 具体的finalize流程:
对象可由两种状态,涉及到两类状态空间,一是终结状态空间 F = {unfinalized, finalizable, finalized};二是可达状态空间 R = {reachable, finalizer-reachable, unreachable}。各状态含义如下:
  • unfinalized: 新建对象会先进入此状态,GC并未准备执行其finalize方法,因为该对象是可达的
  • finalizable: 表示GC可对该对象执行finalize方法,GC已检测到该对象不可达。正如前面所述,GC通过F-Queue队列和一专用线程完成finalize的执行
  • finalized: 表示GC已经对该对象执行过finalize方法
  • reachable: 表示GC Roots引用可达
  • finalizer-reachable(f-reachable):表示不是reachable,但可通过某个finalizable对象可达
  • unreachable:对象不可通过上面两种途径可达
状态变迁图:

变迁说明:
  1. 新建对象首先处于[reachable, unfinalized]状态(A)
  2. 随着程序的运行,一些引用关系会消失,导致状态变迁,从reachable状态变迁到f-reachable(B, C, D)或unreachable(E, F)状态
  3. 若JVM检测到处于unfinalized状态的对象变成f-reachable或unreachable,JVM会将其标记为finalizable状态(G,H)。若对象原处于[unreachable, unfinalized]状态,则同时将其标记为f-reachable(H)。
  4. 在某个时刻,JVM取出某个finalizable对象,将其标记为finalized并在某个线程中执行其finalize方法。由于是在活动线程中引用了该对象,该对象将变迁到(reachable, finalized)状态(K或J)。该动作将影响某些其他对象从f-reachable状态重新回到reachable状态(L, M, N)
  5. 处于finalizable状态的对象不能同时是unreahable的,由第4点可知,将对象finalizable对象标记为finalized时会由某个线程执行该对象的finalize方法,致使其变成reachable。这也是图中只有八个状态点的原因
  6. 程序员手动调用finalize方法并不会影响到上述内部标记的变化,因此JVM只会至多调用finalize一次,即使该对象“复活”也是如此。程序员手动调用多少次不影响JVM的行为
  7. 若JVM检测到finalized状态的对象变成unreachable,回收其内存(I)
  8. 若对象并未覆盖finalize方法,JVM会进行优化,直接回收对象(O)
  9. 注:System.runFinalizersOnExit()等方法可以使对象即使处于reachable状态,JVM仍对其执行finalize方法

4. 一些代码示例

(1) 对象复活

[java]  view plain copy
  1. public class GC {
  2. public static GC SAVE_HOOK = null;
  3. public static void main(String[] args) throws InterruptedException {
  4. SAVE_HOOK = new GC();
  5. SAVE_HOOK = null;
  6. System.gc();
  7. Thread.sleep(500);
  8. if (null != SAVE_HOOK) { //此时对象应该处于(reachable, finalized)状态
  9. System.out.println(”Yes , I am still alive”);
  10. } else {
  11. System.out.println(”No , I am dead”);
  12. }
  13. SAVE_HOOK = null;
  14. System.gc();
  15. Thread.sleep(500);
  16. if (null != SAVE_HOOK) {
  17. System.out.println(”Yes , I am still alive”);
  18. } else {
  19. System.out.println(”No , I am dead”);
  20. }
  21. }
  22. @Override
  23. protected void finalize() throws Throwable {
  24. super.finalize();
  25. System.out.println(”execute method finalize()”);
  26. SAVE_HOOK = this;
  27. }
  28. }

(2)覆盖finalize方法以确保资源释放

作为一个补充操作,以防用户忘记“关闭“资源,JDK中FileInputStream、FileOutputStream、Connection类均用了此”技术“,下面代码摘自FileInputStream类

[java]  view plain copy
  1. /**
  2. * Ensures that the <code>close</code> method of this file input stream is
  3. * called when there are no more references to it.
  4. *
  5. * @exception  IOException  if an I/O error occurs.
  6. * @see        java.io.FileInputStream#close()
  7. */
  8. protected void finalize() throws IOException {
  9. if ((fd != null) &&  (fd != FileDescriptor.in)) {
  10. /* if fd is shared, the references in FileDescriptor
  11. * will ensure that finalizer is only called when
  12. * safe to do so. All references using the fd have
  13. * become unreachable. We can call close()
  14. */
  15. close();
  16. }
  17. }

参考:

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/484934
The Finalizable Object  http://www.artima.com/interfacedesign/Finalizable.html

finalize()相关推荐

  1. Object的finalize()方法的作用是否与C++的析构函数作用相同

    Object的finalize()方法的作用是否与C++的析构函数作用相同 public class Finalization {private static Finalization finaliz ...

  2. java object finalize_Java Object finalize() 方法

    Object finalize() 方法用于实例被垃圾回收器回收的时触发的操作. 当 GC (垃圾回收器) 确定不存在对该对象的有更多引用时,对象的垃圾回收器就会调用这个方法. 语法 protecte ...

  3. Finalize/Dispose/Destructor

    我总是会搞混这些东西,还是写下来帮助记忆. Finalize 即Object.Finalize(),C#中不允许使用Finalize,析构器就等价于Finalize. Destructor 析构器(D ...

  4. .net内存回收与Dispose﹐Close﹐Finalize方法

    .net内存回收与Dispose﹐Close﹐Finalize方法 一. net的对象使用一般分为三种情况﹕ 1.创建对象 2.使用对象 3.释放对象 二.创建对象 1.创建对象实际分为两个步骤﹕变量 ...

  5. 3.1、final、finally、 finalize

    final 可以用来修饰类.方法.变量,分别有不同的意义,final 修饰的 class 代表不可以继承扩展,final 的变量是不可以修改的,而 final 的方法也是不可以重写的(override ...

  6. final finally finalize 的区别

    1.final final修饰类,说明这个类不能被继承,是以个顶级类. final修饰变量,说明这个变量是常量. final修饰方法,表示这个方法不能被重写,不过可以冲在final方法. 比如有个基类 ...

  7. 对于一些手机内存概念的思考、深入理解java的finalize,对于内存优化的小总结...

    2019独角兽企业重金招聘Python工程师标准>>> 最近在对手机性能做了一些小概念总结,方便对于自己的个人思考 Shallow Size: 对象本身占用的内存空间,不包含其引用的 ...

  8. final,finally,finalize的区别

    1.final 修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承.因此一个类不能既被声明为 abstract的,又被声明为final的.将变量或方法声明为 ...

  9. Java将弃用finalize()方法?

    最近,OpenJDK邮件组core-libs-dev里出现了一封邮件,建议弃用Object类的finalize()方法. \\ 弃用Object类的方法将会是一件非常不寻常的事情.Java从 1.0开 ...

  10. java final 变量 回收_java入门教程-Java中final,finally,finalize三个关键字的区别

    final 当这个关键字修饰一个类时,意味着他不能派生出新的子类,也就是说不能被继承,因此一个类不能被同时声明为abstract和final.当final修饰变量或者方法时,可以保证他们在使用中不会被 ...

最新文章

  1. 网站位置服务器,如何查看网站的服务器位置
  2. linux fork, system, exec()
  3. 解决IntelliJ IDEA下Maven报错Unknown lifecycle phase “.test.skip=true“. You must specify a valid lifecycle
  4. 消息中间件系列(八):Kafka、RocketMQ、RabbitMQ等的优劣势比较
  5. § Transitive Intransitive Verb
  6. ROP_return to dl-resolve学习笔记
  7. 算法笔记:二叉树的序列化和反序列化(剑指 Offer 37)
  8. 深度学习框架间互操作的工具:MMdnn
  9. paip.-Djava.library.path -Djava.ext.dirs= 的区别
  10. excel mac 水晶球_水晶球软件使用crystalball.pptx
  11. 量化小科普【什么是量化?常用的股票量化指标、如何搭建量化交易系统】
  12. 图像处理中关于矩的解释
  13. 如何度量两幅图像的相似度--结构相似度 SSIM 原理及代码
  14. OpenCV训练分类器制作xml文档
  15. win 7硬盘安装centos7 亲测可行
  16. 一个文本回射C/S程序并讨论:fork、信号处理机制、僵死进程处理
  17. 2020/5/4/ 每日一咕
  18. 【技术美术图形部分】图形渲染管线2.0-GPU管线概述几何阶段
  19. 1.微信好友定时发送信息
  20. Google英文word2vec预训练模型 word2vec-GoogleNews-vectors

热门文章

  1. 在Remix中运行合约JS脚本
  2. “就业”or“创业”,大学生毕业如何选择,校园市场是新出路?
  3. 开源创新 协同融合|2023 开放原子全球开源峰会开源协作平台分论坛即将启幕
  4. ESP32系列--第十篇 ADC电阻网络按键
  5. ZOJ3775:?(_o)!
  6. android fastboot模式,Fastboot是什么意思 fastboot模式怎么进入?
  7. winform c# 获取电脑配置信息和cpu 内存使用率
  8. AI音乐创作,让每一个人都成为音乐家
  9. systemdd-dev病毒杀
  10. 麻将胡牌算法(遍历+剪枝)