JVM基础(4)——JVM存活判定算法

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

学习必须往深处挖,挖的越深,基础越扎实!

阶段1、深入多线程

阶段2、深入多线程设计模式

阶段3、深入juc源码解析

阶段4、深入jdk其余源码解析

阶段5、深入jvm源码解析

一、简介

我们在 JVM垃圾回收机制一章中,简单介绍了JVM的垃圾回收机制,先来回顾下,系统运行时创建的对象优先在Java堆内存区域分配:

然后新生代里的对象越来越多,当快满了的时候就会触发“Minor GC”,把新生代中的一些对象回收掉:

那么这里就涉及一个问题: JVM如何知道要去回收哪些对象? 这其实就是JVM的对象存活判定机制,主要涉及两种算: 可行性分析算法 和 引用计数算法 。

引用计数算法,是给对象添加一个引用计数器,每当有一个地方引用它时,计数器就加1,当引用失效时,计数器值就减1,任何时刻计数器为0的对象就是可以被回收的。

由于Java语言没有选用引用计数法来管理JVM内存,所以本文不赘述,而且引用计数法不能很好的解决循环引用的问题(Python采用的是引用计数法)。

二、可达性分析算法

可达性分析算法(GC Root Tracing ),其基本思路就是通过一系列的名为" GC Roots "的对象作为起始点,从这些起始点开始搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时(即从 GC Roots 到这个对象不可达),则证明此对象是不可用的,就可以被回收。

GC Roots包括:

  • Java虚拟机栈中的局部变量(指向着GC堆里的对象);
  • VM的一些静态数据结构里指向GC堆里的对象的引用,例如HotSpot VM里的Universe里有很多这样的引用;
  • 所有当前被加载的Java类(看情况);
  • Java类的运行时常量池里的引用类型常量;
  • String常量池(StringTable)里的引用。

可达性分析算法最难理解的就是该选取哪些对象作为GC Roots,我们通过两个示例来看下。

2.1 示例一

下面是最常见的一种情况:

    public class Kafka {public static void main(String[] args) {loadReplicasFromDisk();}public static void loadReplicasFromDisk(){ReplicaManager replicaManager = new ReplicaManager();}}

当执行到loadReplicasFromDisk()时,对应的JVM内存数据结构如下图:

假如此时新生代的内存已经快满了,发生了“Minor GC”,那么JVM会分析ReplicaManager对象的可达性,发现它被“replicaManager”这个局部变量引用着,在JVM规范中, 局部变量是可以作为GC Roots的 ,所以就不会被回收。

2.2 示例二

另一种比较常见的情况,是下面这种样子:

    public class Kafka {public static ReplicaManager replicaManager = new ReplicaManager();}

对应的JVM内存数据结构如下图:

假如此时新生代的内存已经快满了,发生了“Minor GC”,那么JVM会分析ReplicaManager对象的可达性,发现它被“replicaManager”这个方法区中的静态变量引用着,在JVM规范中, 静态变量是可以作为GC Roots的 ,所以就不会被回收。

三、Java引用类型

可达性分析与Java的引用类型有关联,为了更好的管理对象的内存,更好的进行垃圾回收,JVM团队扩展了引用类型,从最早的强引用类型增加到 强引用 、 软引用 、 弱引用 、 虚引用 四个引用类型:

3.1 强引用(StrongReference)

默认的对象都是强引用类型,如果JVM在对象存活判定时,通过GC Roots可达性分析结果为可达,表示引用类型仍然被引用着,这类对象始终不会被垃圾回收器回收。比如下面这段代码:

    public class Kafka {public static ReplicaManager replicaManager = new ReplicaManager();}

3.2 软引用(SoftReference)

在JVM内存充足的情况下,软引用是不会被GC回收的, 只有在JVM内存不足的情况下,才会被GC回收 。比如下面这段代码:

    public class Kafka {public static SoftReference<ReplicaManager> replicaManager = new SoftReference<ReplicaManager>(new ReplicaManager());}

适用场景: 网页缓存、图片缓存

3.3 弱引用(WeakReference)

不论当前JVM内存是否充足,都 只能存活到下一次垃圾收集之前 ,说的直白点,只要发生GC弱引用对象就会被回收,比如下面这段代码:

    public class Kafka {public static WeakReference<ReplicaManager> replicaManager = new WeakReference<ReplicaManager>(new ReplicaManager());}

ThreadlLocal中定义的ThreadLocalMap就使用到的弱引用。ThreadLocalMap的Entry,其Key就是一个弱引用对象,读者可以参考我的《Java多线程系列》。

3.4 虚引用(PhantomReference)

虚引用,不会影响对象的生命周期,所持有的引用就跟没持有一样,随时都能被GC回收。在使用虚引用时,必须和 引用队列 关联使用。其使用场景是用来跟踪对象被垃圾回收器回收的活动。

在对象的垃圾回收过程中,如果GC发现一个对象还存在虚引用,则会把这个 虚引用加入到与之关联的引用队列 中。

程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象内存被回收之前采取必要的行动防止被回收。

四、finalize方法

大家理解完了GC Roots和引用类型的概念,基本就都知道了哪些对象可以被回收,哪些对象不可以被回收:

有GC Roots引用的对象不能回收,没有GC Roots引用的对象,如果是软引用或弱引用,可能会被回收。

真正的回收环节,待被回收的对象其实还有一次机会拯救自己,那就是对象的finalize()方法。我们通过一段代码示例来看下:

    public class ReplicaManager {public static ReplicaManager instance;@Overrideprotected void finalize() throws Throwable {ReplicaManager.instance = this;}}

假如有一个ReplicaManager对象马上就要被回收了(此时已经没有GC Roots到达它的链路),此时GC会首先调用下该对象的finalize()方法,看看它是否找了一个新的GC Roots来引用自己,比如上述代码中,GC发现有个静态变量instance引用了该实例,那GC就不会去回收它。

finalize方法没事不要去重写,这都是GC内部的机制,平时也几乎不用。

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

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

相关文章

C++ 实现十大排序算法

教你手撕排序&#xff0c;这里有一个概念就是稳定排序。假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录&#xff0c;若经过排序&#xff0c;这些记录的相对次序保持不变&#xff0c;即在原序列中&#xff0c;r[i]r[j]&#xff0c;且r[i]在r[j]之前&#…

第十三讲 单片机驱动彩色液晶屏 bin档的烧录方法

单片机驱动TFT彩色液晶屏系列讲座 目录 第一讲 单片机最小系统STM32F103C6T6通过RA8889驱动彩色液晶屏播放视频 第二讲 单片机最小系统STM32F103C6T6控制RA8889驱动彩色液晶屏硬件框架 第三讲 单片机驱动彩色液晶屏 控制RA8889软件:如何初始化 第四讲 单片机驱动彩色液晶屏 控…

Java生成四位数随机验证码

引言&#xff1a; 我们生活中登录的时候都要输入验证码&#xff0c;这些验证码是为了增加注册或者登录难度&#xff0c;减少被人用脚本疯狂登录注册导致的一系列危害&#xff0c;减少数据库的一些压力。 毕竟那些用脚本生成的账号都是垃圾账号 本次实践&#xff1a;生成这样的…

CMake+QT+大漠插件的桌面应用开发

文章目录 CMakeQT大漠插件的桌面应用开发简介环境项目结构配置编译环境代码 CMakeQT大漠插件的桌面应用开发 简介 在CMake大漠插件的应用开发——处理dm.dll&#xff0c;免注册调用大漠插件中已经说明了如何免注册调用大漠插件&#xff0c;以及做了几个简单的功能调用&#x…

【STM32】STM32学习笔记-USART串口收发HEX和文本数据包(29)

00. 目录 文章目录 00. 目录01. 串口简介02. 串口收发HEX数据包接线图03. 串口收发HEX数据包示例104. 串口收发HEX数据包示例205. 串口收发文本数据包接线图06. 串口收发文本数据包示例07. 程序示例下载08. 附录 01. 串口简介 串口通讯(Serial Communication)是一种设备间非常…

科研绘图(五)玫瑰图

柱状图的高级平替可视化 “玫瑰图”&#xff0c;通常也被称为“科克斯图”。它类似于饼图&#xff0c;但不同之处在于每个部分&#xff08;或“花瓣”&#xff09;的角度相同&#xff0c;半径根据它表示的值而变化。这种可视化工具对于周期性地显示信息非常有用&#xff0c;比…

Spring Boot 中批量执行 SQL 脚本的实践

在Spring Boot应用中&#xff0c;有时候我们需要批量执行存储在数据库中的 SQL 脚本。本文将介绍一个实际的案例&#xff0c;演示如何通过 Spring Boot、MyBatis 和数据库来实现这一目标。 0、数据库层 CREATE TABLE batchUpdate (id INT AUTO_INCREMENT PRIMARY KEY,update_…

TCP连接TIME_WAIT

TCP断开过程: TIME_WAIT的作用: TIME_WAIT状态存在的理由&#xff1a; 1&#xff09;可靠地实现TCP全双工连接的终止 在进行关闭连接四次挥手协议时&#xff0c;最后的ACK是由主动关闭端发出的&#xff0c;如果这个最终的ACK丢失&#xff0c;服务器将重发最终的FIN&#xf…

CSS3中多列布局详解

多列布局 概念&#xff1a;在CSS3之前&#xff0c;想要设计类似报纸那样的多列布局&#xff0c;有两种方式可以实现&#xff1a;一种是"浮动布局"&#xff0c;另一种是“定位布局”。 这两种方式都有缺点&#xff1a;浮动布局比较灵活&#xff0c;但不容易控制&…

用Python“自动连发消息”

自动连发消息&#xff0c;基本上C和Python的思路都是不停的模拟“击键”操作&#xff0c;还有一种VB的脚本写法&#xff0c;反成每种语言都能写&#xff0c;更厉害的可以用java做出个GUI界面&#xff0c;先上代码。 一 代码 import pyautogui # 鼠标 import p…

C++力扣题目101--对称二叉树

101. 对称二叉树 力扣题目链接(opens new window) 给定一个二叉树&#xff0c;检查它是否是镜像对称的。 思路 首先想清楚&#xff0c;判断对称二叉树要比较的是哪两个节点&#xff0c;要比较的可不是左右节点&#xff01; 对于二叉树是否对称&#xff0c;要比较的是根节点…

Linux命令之用户账户管理whoami,useradd,passwd,chage,usermod,userdel的使用

1、查看当前用户账户 2、切换用户为root用户 3、新建用户user1&#xff0c;给用户user1设置密码为password123 4、新建用户user2&#xff0c;UID为510&#xff0c;指定其所属的私有组为group1&#xff08;group1组的标识符为500&#xff09;&#xff0c;用户的主目录为/home/us…

codesys【程序】

FB&#xff1a; 用于实现 PLC【叠】PLC FB功能块&#xff1a; 包含 输入&#xff0c;输出&#xff0c;局部变量&#xff0c;静态变量 用ST语言&#xff0c;方便复制。FUNCTION_BLOCK FB_CAN轴 VAR_INPUT 输入 END_VAR VAR_OUTPUT 输出 END_VAR VAR …

【MATLAB源码-第110期】基于matlab的哈里斯鹰优化算发(HHO)无人机三维路径规划,输出做短路径图和适应度曲线。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 哈里斯鹰优化算法&#xff08;Harris Hawk Optimization, HHO&#xff09;是一种受自然界捕食行为启发的优化算法。它基于哈里斯鹰的捕猎策略和行为模式&#xff0c;主要用于解决各种复杂的优化问题。这个算法的核心特征在于…

vue3-列表渲染

v-for 我们可以使用 v-for 指令基于一个数组来渲染一个列表。 v-for 指令的值需要使用 (item in items) 形式的特殊语法&#xff0c;其中 items 是源数据的数组&#xff0c;而 item 是迭代项的别名&#xff0c; (item, index) in items index 表示当前项的位置索引(可选参数)…

深度学习-标注文件处理(txt批量转换为json文件)

接上篇&#xff0c;根据脚本可将coco128的128张图片&#xff0c;按照比例划分成训练集、测试集、验证集&#xff0c;同时生成相应的标注的labels文件夹&#xff0c;最近再看实例分离比较火的mask rcnn模型&#xff0c;准备进行调试但由于实验室算力不足&#xff0c;网上自己租的…

JVM知识总结(持续更新)

这里写目录标题 java内存区域程序计数器虚拟机栈本地方法栈堆方法区运行时常量池 对象的创建 java内存区域 Java 虚拟机在执行 Java 程序的过程中会把它管理的内存划分成若干个不同的数据区域&#xff1a; 程序计数器虚拟机栈本地方法栈堆方法区 程序计数器 记录下一条需要…

【ArcGIS遇上Python】ArcGIS Python批量筛选多个shp中指定字段值的图斑(以土地利用数据为例)

文章目录 一、案例分析二、提取效果二、代码运行效果三、Python代码四、数据及代码下载一、案例分析 以土地利用数据为例,提取多个shp数据中的旱地。 二、提取效果 原始土地利用数据: 属性表: 提取的旱地:(以图层名称+地类名称命名)

基于python舆情分析可视化系统+情感分析+爬虫+机器学习(源码)✅

大数据毕业设计&#xff1a;Python招聘数据采集分析可视化系统✅ 毕业设计&#xff1a;2023-2024年计算机专业毕业设计选题汇总&#xff08;建议收藏&#xff09; 毕业设计&#xff1a;2023-2024年最新最全计算机专业毕设选题推荐汇总 &#x1f345;感兴趣的可以先收藏起来&…

Python 自学(八) 之模块

目录 1. import语句导入模块 P206 2. from ... import 语句导入模块 P207 3. 模块的搜索目录 sys.path P209 4. 以主程序的形式执行 __name__ P212 5. python中的包 P213 1. import语句导入模块 P206 同一目录下&…