Spring 只用一招,就摆脱被垃圾回收的命运,拯救了自己

SpringBoot ApplicationContext 会被 JVM 当成垃圾对象,然后回收掉吗?

最近五阳哥在复习JVM 垃圾回收的知识,被别人问到这个问题,我心里感到一惊,如果Spring 被回收掉,Spring管理的bean全部会被回收,那我们的Java应用不就被一锅端了吗? 这太可怕了……

虽然我相信 Spring一定会处理好这个问题,确保自身不被垃圾回收,但是巨大的好奇心,驱使我一探究竟。

我们在岁月静好时,Spring帮我们做了哪些事情?

回顾一下,垃圾回收的基础知识

精通Java GC的可以跳过这一段。

五阳哥,前两天写了一篇文章,分析为什么gc一定需要Stop the world? # 点击查看,这篇文章? ,里面已经总结道,“当一个对象无法被 GC Root引用到,那么这个对象将在接下来的垃圾回收过程中被回收”。

在Java堆中,存放着所有Java的对象实例。在进行垃圾收集之前,JVM需要确定哪些对象已经不被使用(即垃圾),哪些对象仍然被使用。为了判断对象是否是“垃圾”,JVM采用了可达性分析算法。

可达性分析算法 是指通过指定 GC Root 根对象,从根对象开始搜索引用的对象,通过引用链条,层层遍历链条上的对象,可以到达的对象不可被垃圾回收。而最终没有被搜索遍历到的对象,则为 不可达对象,应该被垃圾回收。

JVM中的 GC Root根对象包括如下:

  1. 虚拟机栈引用的对象
  2. 本地方法栈内JNI(本地方法)引用的对象
  3. 方法区中类静态属性引用的对象
  4. 方法区中常量引用的对象
  5. Java虚拟机内部的引用

如果 Spring 想不被垃圾回收,那么Spring一定要确保自己被以上 GC Root引用,以上五个,任意一个即可。

接下来,我们将分析Spring 源码!找到Spring不被垃圾回收的奥秘!

启动Spring Boot应用

以下代码启动了一个Spring Boot应用,这是官方推荐的启动方式,通过注解的方式,把启动类传递给 SpringApplication ,调用run 方法,启动Spring Boot。

614c38849578dd569a87136361a46739.jpeg

需要说明的是,run方法在Spring boot启动成功后,会立即返回,不会被阻塞。所以 main 线程在启动Spring boot后,将退出……

由于Spring Boot会启动Jetty/Tomcat等其他线程池,所以Java应用并不会退出。因为Java进程退出条件之一是:所有非守护线程全部退出,则JVM退出 点击查看 JVM 如何退出的详细信息 ,所以只有 main 线程退出,其他业务线程还存在情况下,Java不会退出。

由此可见,main 线程在启动 Spring Boot后,并不会一直持有 Spring boot 对象引用,官方文档里也没有 强调,一定要保持 main 线程 不退出。Spring Boot需要把自己交到其他对象手中,确保自己不被回收!

那么如何保证 Spring Boot不被垃圾回收呢?我需要从 SpringApplcaition 内部找原因!

Spring Boot 和 Tomcat

从上面的代码可以看到 Spring Boot控制了Java应用的入口,而Web容器 Tomcat等被Spring 管理,如果Spring不会被垃圾回收,那么Tomcat就不用担心被垃圾回收。

而在Spring Boot之前的Web应用,都是将Java项目打包到Tomcat容器中执行。那时候 Spring MVC和Spring 是要被Tomcat容器管理的,所以那时的Spring项目不用担心 被垃圾回收的问题。

而现在 Tomcat和 Spring boot的角色互换,决定了 Spring Boot应用必须要处理好垃圾回收问题!

探究Spring Boot代码

创建和启动上下文

下图是 SpringApplication.run方法的源代码,run 方法主要执行两步,创建 Spring 上下文和启动上下文。 91d550c1a26f19b841a1543cb3209548.jpeg

刷新上下文的奥秘

在Spring Boot刷新上下文的代码中,首先调用 Spring Application.refresh方法启动Spring 上下文。然后 Spring boot就把 Close 方法注册到 Java shutdownHook 关闭钩子程序中!

d3eccb830c26f73fb5be16be0c68a081.jpeg基本上可以破案了!

因为Spring Boot控制了Java程序的入口,所以要负责整个项目的关闭流程,于是它 注册了Java关闭钩子。

76f4004b3d07d79cdfbb972761261dfa.jpeg

接下来,我们看一下注册关闭钩子,会被 GC Root引用到吗?

关闭钩子

add 方法,将钩子程序注册到 一个容器中!

0e6d56f752344e6ea59857690c1f1fda.jpeg

可以看到 Thread 类型的 钩子程序,被保存在 hooks Map 中。

而hooks列表的类型定义是 static 类型的。 static 变量都是GC Root。

2a72e97a37e725a1b268d3e7aff48d82.jpeg

总结

Spring Boot 在启动时会将关闭流程注册到 Java 关闭钩子中,并通过关闭钩子线程引用到 Spring 上下文。

关闭钩子会被保存在一个 static 静态类型的 Map 中,这个 Map 在 GC Root 上。

因此,Spring Boot 不被垃圾回收的关键是在启动时注册了关闭钩子。

破案了,spring永远不会被垃圾回收。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/176438.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux系统简介与开源精神

🎥 屿小夏 : 个人主页 🔥个人专栏 : Linux系统理论 🌄 莫道桑榆晚,为霞尚满天! 文章目录 📑前言🌤️Linux系统背景☁️UNIX发展史☁️Linux发展史☁️Linux系统企业应用现…

TDengine 与煤科院五大系统实现兼容性互认,助力煤矿智能化安全体系搭建

近日,涛思数据与煤炭科学技术研究院(以下简称煤科院)已完成数个产品兼容互认证工作,经双方共同严格测试,涛思数据旗下物联网、工业大数据平台 TDengine V3.X 与煤炭科学技术研究院旗下煤矿复合灾害监测监控预警系统、煤…

LeetCode算法心得——高级访客(模拟枚举+小窗口)

大家好,我是晴天学长,今天的周赛第二题,需要的小伙伴可以关注支持一下哦!后续会继续更新的。💪💪💪 1) .高级访客 给你一个长度为 n 、下标从 0 开始的二维字符串数组 access_times 。对于每个 …

μC/OS-II---计时器管理1(os_tmr.c)

目录 创建一个计时器重新启动一个计时器停止一个计时器删除一个计时器 计时器是倒计时器,当计数器达到零时执行某个动作。用户通过回调函数提供这个动作。回调函数是用户声明的函数,在计时器到期时被调用。在回调函数中绝对不能进行阻塞调用(…

Ansible playbook详解

playbook是ansible用于配置,部署,和被管理被控节点的剧本 playbook常用的YMAL格式:(文件名称以 .yml结尾) 1、文件的第一行应该以 "---" (三个连字符)开始,表明YMAL文件的开始。    2、在同一…

原型制作神器ProtoPie的使用Unity与网页跨端交互

什么是ProtoPie? ProtoPie是一款面向设计师的软件原型设计工具,例如制作App界面交互展示,制作好的原型可以一键发布到Web服务器,就可以浏览器访问。由于其内置了大量常用交互类型,以及"程序化"模块&#xf…

hash算法

一、Hash散列算法介绍 1.引言 每个人在这个社会上生存,都会有一个属于自己的标记,用于区分不同的个体。通常使用名字就可以了。但是一个名字也并不能完全表示一个人,因为重名的人很多。所以我们可以使用一个身份证号或者指纹来表示独一无二…

力扣每日一道系列 --- LeetCode 160. 相交链表

📷 江池俊: 个人主页 🔥个人专栏: ✅数据结构探索 ✅LeetCode每日一道 🌅 有航道的人,再渺小也不会迷途。 LeetCode 160. 相交链表 思路: 首先计算两个链表的长度,然后判断两个链…

Open X-Embodiment 超大规模开源真实机器人数据集分享

近期,Google旗下的前沿人工智能企业DeepMind汇集了来自 22 种不同机器人类型的数据,创建了 Open X-Embodiment 数据集并开源了出来。该数据集让他们研发的RT-2 机器人在制造和编程方式上有了重大飞跃。 有分析称,在上述数据集上训练的 RT-2-…

gpt-4-turbo、gpt-4v、dall-e-3 api实测!

上周GPT大更新,不仅开放了GPT-4-Turbo、GPT-4-Vision等模型api,还发布了GPTs,使得用户能够根据需要定义自己的GPT应用,OpenAI在这波AI革命上又一次震撼世人。 笔者也在上周拿到了几个新模型的api资格,一直盼着可以测试…

专业的SRM系统全流程管理服务

一、什么是SRM系统 SRM系统,即供应商关系管理,是供应链管理中的重要组成部分,帮助企业与供应商建立、维护和改善业务关系,以实现双方共赢。本文将从供应商寻源到合同签订、订单履行、到付款及供应商评价等环节,阐述SR…

【MybatisPlus】条件构造器、自定义SQL、Service接口

🐌个人主页: 🐌 叶落闲庭 💨我的专栏:💨 c语言 数据结构 javaEE 操作系统 Redis 石可破也,而不可夺坚;丹可磨也,而不可夺赤。 MybatisPlus 一、条件构造器1.1 基于QueryW…