Java 对象的绝地求生

本贴最后更新于 1648 天前,其中的信息可能已经东海扬尘

一个 Java 对象的一生非常悲情,在需要时产生,在无用时消亡。当一个 Java 对象被可达性分析算法指明 GC Roots 到这个对象不可达时就宣告了这个对象即将面临被消亡的处境。

那么死亡是注定的吗?幸运的是它有一次“自救”的机会。当对象进行可达性分析后发现没有与 GC Roots 相连的引用链,那么它将被标记一次,然后进行一次筛选,条件是此对象是否有必要执行 finalize 方法,假设它这个对象没有重写 finalize 方法或者说这个方法已经调用过了,那么虚拟机就认为没有必要执行了。

当然如果被判定为有必要执行,那么虚拟机会将这些需要执行的对象放置在一个名为 F-Queue 的队列当中,然后一条由虚拟机建立的优先级低的线程去执行他们的 finalize 方法,但不保证一定会等待他们执行结束。原因是如果某个对象的 finalize 方法执行缓慢,或者更加极端的发生了死循环,将导致整个系统崩溃。

finalize 方法是这些被即将消亡的对象唯一生存下来的机会,稍后收集器会对这个 F-Queue 中的对象进行第二次的标记,如果成功自救,那么在这次标记时它将被移出“即将回收”的集合,如果没有成功自救,那就在劫难逃,真的要被回收了。

如何自救

自救的方法只有一个,那就是在唯一执行 finalize 方法的时候重新与引用链上的任何一个对象建立关系,譬如将自己赋值给某个类变量或者对象的成员变量,他就可以存活。那么哪些对象可以成为拯救者呢?

这些对象也就是被称为 GC Roots 的对象,包括一下几种:

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象,譬如各个线程被调用的方法堆栈中使用到的参数,局部变量,临时变量等;
  • 方法区中类静态属性引用的对象;
  • 方法区中常量引用的对象;譬如字符串常量池里的引用;
  • 本地方法栈中 JNI(即一般说的 Native 方法)引用的对象;
  • JVM 虚拟机内部的引用,如基本数据类型对应的 Class 对象,一些常驻的异常对象;(NPE,OutOfMemoryError),还有系统类加载器;
  • 所有被同步锁(synchronized)持有的对象;

除了这些固定的 GC Root 集合外,还有根据内存区域不同,还可以有其他对象临时地加入,一起组成完整的 GC Roots 集合。

代码演示 自救过程

/** * @author: fangcong * @description: * @create: Created by work on 2020-10-22 10:48 **/ public class GcEscape { public static GcEscape SAVE_HOOK = null; public void isAlive(){ System.out.println("yes,i am still alive :)"); } @Override protected void finalize() throws Throwable { super.finalize(); System.out.println("finalize method executed"); GcEscape.SAVE_HOOK = this; //建立GC Root 引用 } public static void main(String[] args) throws Throwable { SAVE_HOOK = new GcEscape(); SAVE_HOOK = null; //断开GC ROOT 引用 等待垃圾回收 System.gc(); //手动执行垃圾回收 //暂停0.5秒,等待线程执行finalize方法(此线程优先级低) Thread.sleep(500); if (SAVE_HOOK != null) { SAVE_HOOK.isAlive(); } else { System.out.println("i am dead"); } SAVE_HOOK = null; //断开GC ROOT 引用 等待垃圾回收 System.gc(); //手动执行垃圾回收 //finalize方法只执行一次,此时不会执行 if (SAVE_HOOK != null) { SAVE_HOOK.isAlive(); } else { System.out.println("i am dead"); } } }

运行结果:

finalize method executed yes,i am still alive :) i am dead

生存是一切,这个对象做了它能做的。但是在开发中并不推荐使用这个方法,代价昂贵,不确定性大。

  • GC
    17 引用 • 45 回帖
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3201 引用 • 8216 回帖 • 1 关注
1 操作
Gakkiyomi2019 在 2020-11-05 10:09:42 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 旅游

    希望你我能在旅途中找到人生的下一站。

    96 引用 • 901 回帖 • 1 关注
  • Lute

    Lute 是一款结构化的 Markdown 引擎,支持 Go 和 JavaScript。

    29 引用 • 202 回帖 • 28 关注
  • Sphinx

    Sphinx 是一个基于 SQL 的全文检索引擎,可以结合 MySQL、PostgreSQL 做全文搜索,它可以提供比数据库本身更专业的搜索功能,使得应用程序更容易实现专业化的全文检索。

    1 引用 • 222 关注
  • 设计模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

    200 引用 • 120 回帖
  • 深度学习

    深度学习(Deep Learning)是机器学习的分支,是一种试图使用包含复杂结构或由多重非线性变换构成的多个处理层对数据进行高层抽象的算法。

    54 引用 • 44 回帖
  • RabbitMQ

    RabbitMQ 是一个开源的 AMQP 实现,服务器端用 Erlang 语言编写,支持多种语言客户端,如:Python、Ruby、.NET、Java、C、PHP、ActionScript 等。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

    49 引用 • 60 回帖 • 344 关注
  • GitLab

    GitLab 是利用 Ruby 一个开源的版本管理系统,实现一个自托管的 Git 项目仓库,可通过 Web 界面操作公开或私有项目。

    46 引用 • 72 回帖
  • Android

    Android 是一种以 Linux 为基础的开放源码操作系统,主要使用于便携设备。2005 年由 Google 收购注资,并拉拢多家制造商组成开放手机联盟开发改良,逐渐扩展到到平板电脑及其他领域上。

    336 引用 • 324 回帖
  • 友情链接

    确认过眼神后的灵魂连接,站在链在!

    24 引用 • 373 回帖 • 1 关注
  • PHP

    PHP(Hypertext Preprocessor)是一种开源脚本语言。语法吸收了 C 语言、 Java 和 Perl 的特点,主要适用于 Web 开发领域,据说是世界上最好的编程语言。

    181 引用 • 408 回帖 • 484 关注
  • 持续集成

    持续集成(Continuous Integration)是一种软件开发实践,即团队开发成员经常集成他们的工作,通过每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。

    15 引用 • 7 回帖
  • 黑曜石

    黑曜石是一款强大的知识库工具,支持本地 Markdown 文件编辑,支持双向链接和关系图。

    A second brain, for you, forever.

    24 引用 • 241 回帖
  • jsoup

    jsoup 是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址、HTML 文本内容。它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方法来取出和操作数据。

    6 引用 • 1 回帖 • 489 关注
  • BAE

    百度应用引擎(Baidu App Engine)提供了 PHP、Java、Python 的执行环境,以及云存储、消息服务、云数据库等全面的云服务。它可以让开发者实现自动地部署和管理应用,并且提供动态扩容和负载均衡的运行环境,让开发者不用考虑高成本的运维工作,只需专注于业务逻辑,大大降低了开发者学习和迁移的成本。

    19 引用 • 75 回帖 • 666 关注
  • Electron

    Electron 基于 Chromium 和 Node.js,让你可以使用 HTML、CSS 和 JavaScript 构建应用。它是一个由 GitHub 及众多贡献者组成的活跃社区共同维护的开源项目,兼容 Mac、Windows 和 Linux,它构建的应用可在这三个操作系统上面运行。

    15 引用 • 136 回帖 • 5 关注
  • Ubuntu

    Ubuntu(友帮拓、优般图、乌班图)是一个以桌面应用为主的 Linux 操作系统,其名称来自非洲南部祖鲁语或豪萨语的“ubuntu”一词,意思是“人性”、“我的存在是因为大家的存在”,是非洲传统的一种价值观,类似华人社会的“仁爱”思想。Ubuntu 的目标在于为一般用户提供一个最新的、同时又相当稳定的主要由自由软件构建而成的操作系统。

    127 引用 • 169 回帖
  • Postman

    Postman 是一款简单好用的 HTTP API 调试工具。

    4 引用 • 3 回帖 • 2 关注
  • danl
    164 关注
  • 又拍云

    又拍云是国内领先的 CDN 服务提供商,国家工信部认证通过的“可信云”,乌云众测平台认证的“安全云”,为移动时代的创业者提供新一代的 CDN 加速服务。

    20 引用 • 37 回帖 • 576 关注
  • Bug

    Bug 本意是指臭虫、缺陷、损坏、犯贫、窃听器、小虫等。现在人们把在程序中一些缺陷或问题统称为 bug(漏洞)。

    76 引用 • 1742 回帖 • 6 关注
  • 安全

    安全永远都不是一个小问题。

    203 引用 • 818 回帖 • 2 关注
  • JWT

    JWT(JSON Web Token)是一种用于双方之间传递信息的简洁的、安全的表述性声明规范。JWT 作为一个开放的标准(RFC 7519),定义了一种简洁的,自包含的方法用于通信双方之间以 JSON 的形式安全的传递信息。

    20 引用 • 15 回帖 • 22 关注
  • 锤子科技

    锤子科技(Smartisan)成立于 2012 年 5 月,是一家制造移动互联网终端设备的公司,公司的使命是用完美主义的工匠精神,打造用户体验一流的数码消费类产品(智能手机为主),改善人们的生活质量。

    4 引用 • 31 回帖 • 2 关注
  • Typecho

    Typecho 是一款博客程序,它在 GPLv2 许可证下发行,基于 PHP 构建,可以运行在各种平台上,支持多种数据库(MySQL、PostgreSQL、SQLite)。

    12 引用 • 67 回帖 • 451 关注
  • 职场

    找到自己的位置,萌新烦恼少。

    127 引用 • 1708 回帖 • 1 关注
  • CentOS

    CentOS(Community Enterprise Operating System)是 Linux 发行版之一,它是来自于 Red Hat Enterprise Linux 依照开放源代码规定释出的源代码所编译而成。由于出自同样的源代码,因此有些要求高度稳定的服务器以 CentOS 替代商业版的 Red Hat Enterprise Linux 使用。两者的不同在于 CentOS 并不包含封闭源代码软件。

    239 引用 • 224 回帖
  • FlowUs

    FlowUs.息流 个人及团队的新一代生产力工具。

    让复杂的信息管理更轻松、自由、充满创意。

    1 引用 • 1 关注