Java finalize()

转载地址:java finalize方法总结、GC执行finalize的过程 - ScaleZ - 博客园 (cnblogs.com)

finalize()介绍

finalize()是Object的protected方法,子类可以覆盖该方法以实现资源清理工作,GC在回收对象之前调用该方法,但Java中的finalize的调用具有不确定性。

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方法

代码示例

评论区的老哥在示例代码加了注释,这边直接复制过来。

public class GC {  public static GC SAVE_HOOK = null;  public static void main(String[] args) throws InterruptedException {// 新建对象,因为SAVE_HOOK指向这个对象,对象此时的状态是(reachable,unfinalized)SAVE_HOOK = new GC();  //将SAVE_HOOK设置成null,此时刚才创建的对象就不可达了,因为没有句柄再指向它了,对象此时状态是(unreachable,unfinalized)SAVE_HOOK = null;  //强制系统执行垃圾回收,系统发现刚才创建的对象处于unreachable状态,并检测到这个对象的类覆盖了finalize方法,因此把这个对象放入F-Queue队列,由低优先级线程执行它的finalize方法,此时对象的状态变成(unreachable, finalizable)或者是(finalizer-reachable,finalizable)System.gc();  // sleep,目的是给低优先级线程从F-Queue队列取出对象并执行其finalize方法提供机会。在执行完对象的finalize方法中的super.finalize()时,对象的状态变成(unreachable,finalized)状态,但接下来在finalize方法中又执行了SAVE_HOOK = this;这句话,又有句柄指向这个对象了,对象又可达了。因此对象的状态又变成了(reachable, finalized)状态。Thread.sleep(500); // 这里楼主说对象处于(reachable,finalized)状态应该是合理的。对象的finalized方法被执行了,因此是finalized状态。又因为在finalize方法是执行了SAVE_HOOK=this这句话,本来是unreachable的对象,又变成reachable了。 if (null != SAVE_HOOK) { //此时对象应该处于(reachable, finalized)状态  // 这句话会输出,注意对象由unreachable,经过finalize复活了。System.out.println("Yes , I am still alive");  } else {  System.out.println("No , I am dead");  }  // 再一次将SAVE_HOOK放空,此时刚才复活的对象,状态变成(unreachable,finalized)SAVE_HOOK = null;  // 再一次强制系统回收垃圾,此时系统发现对象不可达,虽然覆盖了finalize方法,但已经执行过了,因此直接回收。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()");  // 这句话让对象的状态由unreachable变成reachable,就是对象复活SAVE_HOOK = this;  }
}

Java finalize()的使用相关推荐

  1. java finalize方法总结、GC执行finalize的过程

    java finalize方法总结.GC执行finalize的过程 分类: Java 2013-10-06 16:42  73人阅读  评论(0)  收藏  举报 finalize java jvm ...

  2. java finalize逃脱_关于Java中的finalize()方法

    java提供finalize()方法,垃圾回收器准备释放内存的时候,会先调用finalize(). (1).对象不一定会被回收. (2).垃圾回收不是析构函数. (3).垃圾回收只与内存有关. (4) ...

  3. java finalize方法的使用

    <JAVA编程思想>: Java提供finalize()方法,垃圾回收器准备释放内存的时候,会先调用finalize(). (1).对象不一定会被回收. (2).垃圾回收不是析构函数. ( ...

  4. java finalize 析构_close,析构函数和finalize:Java矛盾

    try { FileInputStream in = new FileInputStream(filename); BufferedReader reader=new BufferedReader(n ...

  5. java finalize 何时被调用_finalize()方法什么时候被调用?析构函数(final

    finalize()方法也叫收尾方法. 一旦垃圾回收器准备好释放对象占用的存储空间,首先会去调用finalize()方法①进行一些必要的清理工作(对垃圾回收器不能处理的特殊情况进行处理)(例子在下边) ...

  6. java finalize逃脱_finalize(),析构函数(finalization)

    对象生存还是死忙(finalize 是什么) 来自:<深入理解Java虚拟机> Object对象里的一个方法 对象内存的回收是由GC来做的,GG通过可达性分析来回收未被引用的对象 但是并不 ...

  7. java finalize 作用_Java编程之详解finalize

    前言 finalize()是Object的protected方法,子类可以覆盖该方法以实现资源清理工作,GC在回收对象之前调用该方法. finalize的作用 (1)finalize()与C++中的析 ...

  8. java finalize逃脱_java finalize方法详解

    1. finalize的作用 finalize()是Object的protected方法,子类可以覆盖该方法以实现资源清理工作,GC在回收对象之前调用该方法. finalize()与C++中的析构函数 ...

  9. java finalize 作用_java中的finalize方法有什么作用

    java中的finalize方法是Object类中提供的一个方法,在GC准备释放对象所占用的内存空间之前,它将首先调用finalize()方法. finalize()方法是Object类中提供的一个方 ...

最新文章

  1. php设置背景图片的代码,css设置背景图片如何实现?(代码实例)
  2. centOS 7 安装man中文版手册
  3. sql exists 的用法
  4. theme vscode 护眼_VS code 豆沙绿护眼主题
  5. java 鼠标拖动图形_java怎么实现鼠标在桌面拖动过程中 画 矩形的 功能?
  6. 使用BlazeDS实现Java和Flex通信之hello world
  7. Zookeeper基于Java访问-节点事件监听
  8. css sprite讲解与使用实例
  9. java stream findany_Java Stream findFirst() vs findAny() API With Example
  10. 解决gilde加载圆角和CenterCrop冲突的问题
  11. php怎么生成word模板,PHP 使用word模板生成word文档示例
  12. html 表格输出excel,html中导出excel表格
  13. puppy linux u盘 分区,让安装在U盘上的Puppy Linux像安装在硬盘上一样工作
  14. java 二进制 表示负数_java中的负数表示
  15. 波士顿房价数据集——预测房价
  16. python 编码转换 专题
  17. 最强大的Docker插件 fabric8io/docker-maven-plugin
  18. 理解C#值类型与引用类型
  19. 深入了解光耦,光耦如何连接进电路中?
  20. MYSQL学习笔记(自用)第九章

热门文章

  1. shell常见的文件属性检查
  2. unistd.h 中int access(const char * pathname, int mode); 判断进程能否以mode模式访问pathname文件(可以用来判断文件/目录是否存在)...
  3. bacula 的安装、配置和运行
  4. 除非另外还指定了 TOP 或 FOR XML,否则,ORDER BY 子句在视图、内联函数、派生表、子查询...
  5. C#文件和文件文件夹按时间、名称排序-顺序与倒序
  6. 从Web借鉴UI设计
  7. 学习 WCF (5)--学习Binding的使用
  8. C#抓取网页程序的实现浅析
  9. 定义应用程序的基础--模式(Bridge-桥接,Factory-工厂)
  10. mysql int(3)与int(11)的区别详解