生存还是死亡

C++必须手动释放内存, 而Java有Garbage Collection(垃圾回收机制), 自动释放内存, 那么gc是如何判断一个对象是否已经死亡, 是否该回收它了? 这就需要一个垃圾回收算法

可达性分析算法

在Java中使用的是可达性分析算法, 就是对象到gc roots是否直接或者间接性可达, 可达就还活着, 不可达就是死了, 要回收了

在这张图中, Object1、Object2、Object3是连在GC Roots上的, 而Object4没有, Object4就很有可能快被gc回收了

什么是finalize方法

finalize英文是终结的意思, 我认为这个方法可以理解为每个对象的"最后遗言", 快要被gc回收前执行的方法 ,不过有没有说遗言的机会还不一定呢…

执行finalize方法的时机

由于垃圾回收的不确定性, gc不能保证一个对象的finalize方法一定会被执行, 即便是System.gc()亦或者是System.runFinalization()也仅仅是提醒JVM要进行垃圾回收了, 仅仅是个建议, 到底要不要执行, 还是JVM说了算
一个对象死亡消失前, 至少要被标记两次, 第一次就是JVM通过可达性算法检测到它无法连接到gc roots, 如上面的Object4, 它会被标记一次并放入一个即将送往"断头台"的队列中, 如果这个对象没有重写finalize方法或者已经执行过finalize方法,它就会被标记第二次,基本死翘翘了.
所以,finalize必须要重写才有可能执行, 而且最多只会执行一次.
那假如我们在finalize方法中让对象重新连接上GC Roots, 那不就可以救活它了吗?finalize方法好比是它一块唯一的、一次性的"免死金牌",像是电视里面骑着马赶来大喊一声"刀下留人"的场景, 有没有点像, 哈哈

实现对象的自我拯救

public class FinalizeDemo {//声明一个引用private static FinalizeDemo finalizeDemo = null;//判断对象是否可达gc rootspublic static void isAlive() {if (FinalizeDemo.finalizeDemo != null) {System.out.println("我还活着!");} else {System.out.println("我死了..");}}@Overrideprotected void finalize() throws Throwable {//把自身赋值给声明的引用,连接上gc rootsfinalizeDemo = this;System.out.println("连上GC roots, 抓住了救命稻草!");}public static void main(String[] args) {//new一个对象,对gc roots不可达, 即将面临死亡new FinalizeDemo();//建议gc进行垃圾回收,并执行finalize方法System.gc();System.runFinalization();//看看它死了还是活着FinalizeDemo.isAlive();//断开和gc roots的连接,现在为不可达finalizeDemo = null;System.gc();System.runFinalization();FinalizeDemo.isAlive();}
}

在主方法中,new了一个即将面临被回收的对象, 它通过finalize方法连接上gc roots才捡回了一命,当它断开连接后, 又面临着即将被回收的命运, 本想再次调用finalize方法救自己, 可是它的finalize方法已经被执行过一次了, 不会再执行了,所以只能"死亡"了
运行结果:

悲剧艺术! finalize方法实现对象的自我拯救相关推荐

  1. Java中一次对象的自我拯救探究

    <深入理解java虚拟机>第二版 67页,一次对象自我拯救这个例子很不错,在这里分享出来. 并且从源码角度进行分析. 代码如下: /*** 1 对象可以在被GC时自我拯救* 2 这种自救机 ...

  2. java finalize逃脱_JVM【第十三回】:【Java对象存活------finalize()方法】

    在根搜索算法中不可达的对象,也并非是"非死不可"的,这个时候他们暂时处于"缓刑"阶段,要真正宣告一个对象死亡,至少要经历两次标记过程:如果对象在进行根搜索后发现 ...

  3. java finalize逃脱_Java对象回收与finalize方法

    生存还是死亡 事实上,即使被可达性分析算法判断为不可达,对象也不是"非死不可",对象会先进入"缓刑"状态.要真正宣告一个对象死亡,至少要经历两次标记过程: 如果 ...

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

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

  5. 【Java 虚拟机原理】垃圾回收算法 ( 可达性分析算法 | GC Root 示例 | GC 回收前的两次标记 | finalize 方法示例 )

    文章目录 一.可达性分析算法 二.GC Root 示例 三.GC 回收前的两次标记 四.finalize 方法示例 一.可达性分析算法 在 堆内存 中 , 存在一个 根对象 GC Root , GC ...

  6. Object的finalize方法

    一.一次标记 首先finalize方法是在垃圾回收时,用于确认该对象是否确认被回收的一个标记过程. 确认一个对象真正被回收需要经历两次标记过程: 可达性分析没有引用,这是第一次标记 是否有必要执行fi ...

  7. finalize方法的使用

    finalize方法是Object提供的的实例方法,使用规则如下: 当对象不再被任何对象引用时,GC会调用该对象的finalize()方法 finalize()是Object的方法,子类可以覆盖这个方 ...

  8. java的finalize方法

    我们通常用构造器来创建对象,而Finalize正好相反,构造方法执行对象的初始化操作,finalize方法执行对象的销毁操作. 那我们什么时候需要使用finalize方法呢,我们都知道Java里垃圾回 ...

  9. finalize方法

    ​ finalize()是Object中的方法,当垃圾回收器将要回收对象所占内存时,该方法被调用,即当一个对象被虚拟机宣告死亡时会先调用它的finalize()方法,让此对象临终前交代点遗言,当然对象 ...

最新文章

  1. 新的工作电脑 神州优雅A550-i7
  2. NSNotification先注册监听,再发送消息
  3. 高并发大流量专题---5、CDN加速
  4. Android之getCacheDir()和getFilesDir()方法区别
  5. 设计模式C++实现(5)——桥接模式
  6. 检索每个组中的最后一条记录-MySQL
  7. VS code报错:Launch options string provided by the project system id invalid.
  8. 释放被束缚的页面 – V1.1.0
  9. 114. PHP command line getopt
  10. C/C++[codeup 2064]编排字符串
  11. docker常用操作(七)docker安装gitlab
  12. UWA学堂|逻辑代码模块
  13. go Test Benchmark 性能测试
  14. C语言联合体基本内容
  15. 使用bs4爬取《孙子兵法》(处理string属性遇见<br>标签时提取为空)
  16. 2022-2028年全球与中国摆式斗式提升机市场现状及未来发展趋势分析报告
  17. mxgraph.js实现Topo图
  18. maya linux 安装教程视频,在Archlinux 安装Maya7.01
  19. MATLAB读取文件中的所有同类型数据,并记录其峰值
  20. 多线程应用_左圆右方

热门文章

  1. 【gp数据库】查询函数中引用数据表信息
  2. 阿里云服务器ECS新手搭建
  3. 这几十个前端炫酷库你都知道吗?
  4. mysql创建联合索引_mysql如何创建多个联合索引
  5. 双11电商技术:不再谷满谷,坑满坑,看苏宁库存架构转变
  6. 知识图谱嵌入经典方法(Trans系列、KG2E)
  7. 02. OSI开放式互联参考七层模型
  8. import time python_慢步python,说说import,引用功能代码(功能库、py文件代码)
  9. 中央银行调节货币供应量的三个手段
  10. 索引数组与关联数组的定义及区别