【JVM】垃圾回收机制|死亡对象的判断算法|垃圾回收算法

思维导图

目录

1.找到谁是垃圾

1)引用计数(不是JVM采取的方式,而是Python/PHP的方案)

2)可达性分析(是JVM采用的方案)

2.释放对应的内存的策略

1)标记-清除(并不实用)

2)复制算法

3)标记-整理

4)分代算法


垃圾回收机制GC,是Java提供的对于内存自动回收的机制,相对于C/C++的手动回收malloc free来命名的,GC需要消耗额外的系统资源,而且存在非常影响执行效率的“STW”问题(stop the world),触发GC的时候,就可能一瞬间把系统负载拉满,导致服务器无法响应其他的请求

GC回收的是“内存”,更准确的说是“对象”,回收的是“堆上的内存”

1)程序计数器:不需要额外回收,线程销毁,自然回收了

2)栈::不需要额外回收,线程销毁,自然回收了

3)元数据区:一般也不需要,都是加载类,很少“卸载类”

4):GC的主力

回收一定是一次回收一个完整的对象,不能回收半个对象(一个对象有10个成员,肯定是把10个成员的内存都回收了,而不是只回收一部分)

GC的流程,主要是两个步骤:

1.找到谁是垃圾(即不被继续使用的对象)

2.释放对应的内存


1.找到谁是垃圾

谁是垃圾,这个事情,不太好找;一个对象,什么时候创建,时机往往是明确的,但是什么时候不在使用,时机往往是模糊的...在编程中,一定要确保,代码中使用的每个对象,都得是有效的,千万不要出现“提前释放”的情况(宁可放过,也不能错杀)

因此判定一个对象是否是垃圾,判定方式是比较保守的;此处引入了一个非常"保守“的做法,一定不会误判的做法(可能会释放不及时),判定某个对象,是否存在引用指向它

Test t = new Test();

使用对象,都是通过引用的方式来使用的,如果没有引用指向这个对象,意味着这个对象注定无法在代码中使用,如果没有引用指向的对象就可以视为是垃圾了

Test t = new Test();
t = null;

修改t的指向,此时new Test()的对象就没有引用指向了,此时这个对象就可以认为是”垃圾“

具体怎么判断,某个对象是否有引用指向呢?有很多方式来实现,下面介绍两种方式

如果面试官问:GC中,如何判定对象是垃圾,那么两种都要回答

如果问:Java的GC中,如何判定对象是垃圾,那么只需要回答第二种


1)引用计数(不是JVM采取的方式,而是Python/PHP的方案)

给对象增加⼀个引⽤计数器,每当有⼀个地⽅引⽤它时,计数器就+1;当引⽤失效时,计数器就-1;任何时刻计数器为0的对象就是不能再被使⽤的,即对象已"死"

Test a = new Test();
Test b = a;
//把对象的地址进行赋值,都知道对象的地址了,自然就能找到对象,更能找到对象旁边的计数器了
b = null;
a = null;
//引用计数器为0,此时对象就是垃圾了

 but,这种方案有两个缺陷:

(1)消耗额外的存储空间

如果对象比较大,浪费的空间还好,对象比较小,空间占用就多了,并且对象数目多,空间的浪费就多了

(2)存在”循环引用“的问题(面试考到引用计数的重点)

class Test {Test t;
}Test a = new Test();
Test b = new Test();
a.t = b;
b.t = a;a = null;
b = null;

此时,这两对象相互指向对方,导致两个对象的引用计数都为1(不为0,不是垃圾),但是外部代码,也无法访问到这两个对象

这个问题也是能解决的,需要付出额外的代价(搭配一些其他的机制来解决),Python和PHP通过额外的机制,避免形成循环引用(自动检测是否形成了循环引用,并且给出了一些报错提示)


2)可达性分析(是JVM采用的方案)

解决了空间的问题,也解决了循环引用的问题,但是同时也要付出代价,时间上的代价

JVM把对象之间的引用关系,理解形成了一个”树形结构“;JVM就会不停的遍历这样的结构,把所有能够遍历访问到的对象标记成”可达“,剩下的就是”不可达“

class Node{Node left;Node right;
}Node build() {Node a = new Node();Node b = new Node();Node c = new Node();Node d = new Node();Node e = new Node();Node f = new Node();Node g = new Node();a.left = b;a.right = c;b.left = d;b.right = e;e.left = g;c.right = f;return a;
}Node root = build();
//此处只有一个引用,通过这个引用,就能访问到所有树上的结点对象

 如果a.right = null;

此时c就不可达了,同时f也就不可达了

GC roots(这些数的根节点是怎么确定的?)

Java代码中,你所有的

1)栈上的局部对象,引用类型的,就是GC roots

2)常量池中,引用的对象

3)方法区中的静态成员

很多个上述的树,JVM就会周期性的对这所有的树进行遍历,不停的标记可达,也不停的把不可达的对象干掉;具体树是否复杂,都取决于实际代码的实现(有时会很复杂)

but:由于可达性分析,需要消耗一定的时间,因此Java垃圾回收,没法做到”实时性“,周期性进行扫描(JVM提供了一组专门的负责GC的线程,不停的进行扫描工作)


2.释放对应的内存的策略

1)标记-清除(并不实用)

直接把标记为垃圾对象对应的内存,释放掉(简单粗暴)

白色区域:正在使用的

黑色区域:已经释放的,其他代码可以重复利用的

但是这样的做法会存在”内存碎片“问题,空闲内存被分为一个个的碎片了,后续很难申请到大的内存。申请内存,都是要申请”连续“的内存空间的


2)复制算法

要释放1,3,5,保留2,4,不会直接释放1,3,5的内存,而是把2,4拷贝到另一块空间中

内存碎片的问题就解决了,但是这样空间浪费太多,如果你要保留的对象比较多,复制的时间开销也不小


3)标记-整理

释放2,4,6,保留1,3,5,7

类似于“顺序表删除中间元素”,搬运

这样能解决内存碎片,也能解决空间利用率的问题

但是这样的搬运,时间开销更大


4)分代算法

上述三个方案,只是铺垫,JVM中的实际方案,是综合上述的方案,更复杂的策略,分代回收(即分情况讨论,根据不同的场景/特点选择合适的方案)

把新创建的对象,放到伊甸区,这个区中,大部分的对象,生命周期都是比较短的,第一轮GC到达的时候,就会成为垃圾,只有少数对象能活过第一轮GC

伊甸区->生存区 通过复制算法(由于存活对象较少,复制开销也很低,生存区空间也不必很大)

生存区->生存区  通过复制算法,没经过一轮GC,生存区中都会淘汰掉一批对象,剩下的通过复制算法,进入另一个生存区(进入另一个生存区的还要从伊甸区里进来的对象),成存活下来的对象,年龄+1

生存区->老年代 某些对象,经历了很多轮GC,都没有成为垃圾,就会复制到老年代

老年代的对象,也是需要进行GC的,但是老年代的对象生命周期都比较长,就可以降低GC扫描的频率

综上就是”分代回收“的基本逻辑

对象 伊甸区-> 生存区-> 生存区 ->老年区  复制算法

对象在 老年代中,通过标记-整理(搬运)来进行回收


垃圾回收还有一个话题:垃圾回收器,上述思想的具体实现,实现过程有很多优化和策略的体现

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

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

相关文章

Linux 文件系统(下)

目录 一.文件系统 1.文件在磁盘上的存储方式 a.盘面、磁道和扇区 b.分区和分组 2.有关Block group相关字段详解 a.inode编号 b.inode Table(节点表) c.Data blocks(数据区) d.小结 二.软硬链接 1.软链接 a.软链接的创建…

Netty+HTML5+Canvas 网络画画板实时在线画画

采用Html5的canvas做前端画画板&#xff0c;发送数据到后端Netty服务&#xff0c;实时转发笔迹数据&#xff0c;在线实时同步画笔轨迹&#xff0c;单击绿色小方块&#xff0c;保存画板的图片 页面&#xff1a; <!-- index.html --><!DOCTYPE html> <html> …

【Elasticsearch】-实现向量相似检索

1、http请求方式 如果elasticsearch服务设置账号密码&#xff0c;则在请求的header中添加 Basic Auth 认证 请求方式&#xff1a;Post 请求地址&#xff1a;/index_name/_search 请求body&#xff1a;json格式 {"size": 10, //返回条数"min_score": 0.…

二叉树——数据结构

这次我们来学习一下数据结构中的二叉树 1. 二叉树的概念及结构 1.1 二叉树的定义 定义&#xff1a;所有结点的度小于等于2的树。 上图中可以看出 二叉树不存在度大于2的结点二叉树的子树有左右之分&#xff0c;次序不能颠倒&#xff0c;因此二叉树是有序树。 任意二叉树都…

springboot实战学习(6)(用户模块的登录认证)(初识令牌)(JWT)

接着上篇博客学习。上篇博客是在基本完成用户模块的注册接口的开发以及注册时的参数合法性校验的基础上&#xff0c;基本完成用户模块的登录接口的主逻辑。具体往回看了解的链接如下。 springboot实战学习笔记&#xff08;5&#xff09;(用户登录接口的主逻辑)-CSDN博客文章浏览…

[数据结构与算法·C++版] 笔记 1.2 什么是数据结构

1.2 什么是数据结构 结构&#xff1a;实体 关系数据结构&#xff1a; 按照逻辑关系组织起来的一批数据&#xff0c;按一定的存储方法把它存储在计算机中在这些数据上定义了一个运算的集合 数据结构的逻辑组织 线性结构 线性表&#xff08;表&#xff0c;栈&#xff0c;队列&…

科研绘图系列:R语言多个AUC曲线图(multiple AUC curves)

文章目录 介绍加载R包导入数据数据预处理画图输出结果组图系统信息介绍 多个ROC曲线在同一张图上可以直观地展示和比较不同模型或方法的性能。这种图通常被称为ROC曲线图,它通过比较不同模型的ROC曲线下的面积(AUC)大小来比较模型的优劣。AUC值越大,模型的诊断或预测效果越…

【Linux笔记】虚拟机内Linux内容复制到宿主机的Window文件夹(文件)中

一、共享文件夹 I、Windows宿主机上创建一个文件夹 目录&#xff1a;D:\Centos_iso\shared_files II、在VMware中设置共享文件夹 1、打开VMware Workstation 2、选择需要设置的Linux虚拟机&#xff0c;点击“编辑虚拟机设置”。 3、在“选项”标签页中&#xff0c;选择“共…

数模方法论-整数规划

一、基本概念 非线性规划的应用包括工程设计、资源分配、经济模型等。在求解过程中&#xff0c;由于非线性特性&#xff0c;常用的方法有梯度法、牛顿法、启发式算法等。求解非线性规划问题时&#xff0c;解的存在性和唯一性通常较难保证&#xff0c;且可能存在多个局部最优解…

推荐3个AI论文、AI查重、AI降重工具

什么是AI论文、AI查重、AI降重工具&#xff1f; AI论文 AI论文指的是以人工智能&#xff08;AI&#xff09;相关主题为研究对象的学术论文。这类论文通常包含以下内容&#xff1a; 研究问题&#xff1a;针对某个特定的AI问题或领域的研究。方法&#xff1a;介绍用于解决问题…

yolov8旋转目标检测之绝缘子检测-从数据加载到模型训练、部署

YOLOv8 是 YOLO (You Only Look Once) 系列目标检测算法的最新版本&#xff0c;以其高速度和高精度而著称。在电力行业中&#xff0c;绝缘子是电力传输线路上的重要组件之一&#xff0c;它们用于支撑导线并保持电气绝缘。由于长期暴露在户外环境中&#xff0c;绝缘子容易出现损…

Netty源码-业务流程之构建连接

Netty基本介绍&#xff0c;参考 Netty与网络编程 1、Netty构建连接 构建连接的流程 1.1 我们知道客户端连接服务端都是通过NioEventLoop来处理请求&#xff0c;NioEventLoop是一个线程&#xff0c;连接进来首先进入run()方法。 所以我们需要启动服务端&#xff0c;然后再启动…

一个安卓鸿蒙化工具

DevEco插件&#xff0c;为已有安卓项目鸿蒙化加速。 目前支持&#xff1a; 1、安卓Vector Assets转svg&#xff1b; 2、json转ets model&#xff1b; 3、kotlin model转ets model&#xff1b; 下载地址&#xff1a;andtoharplugin1.1.0 安装&#xff1a; deveco插件安装选硬…

Java笔试面试题AI答之设计模式(2)

文章目录 6. 什么是单例模式&#xff0c;以及他解决的问题&#xff0c;应用的环境 &#xff1f;解决的问题应用的环境实现方式 7. 什么是工厂模式&#xff0c;以及他解决的问题&#xff0c;应用的环境 &#xff1f;工厂模式简述工厂模式解决的问题工厂模式的应用环境工厂模式的…

我的AI工具箱Tauri版-VideoIntroductionClipCut视频介绍混剪

本教程基于自研的AI工具箱Tauri版进行VideoIntroductionClipCut视频介绍混剪。 本项目为自研的AI工具箱Tauri版中的视频剪辑模块&#xff0c;专注于自动生成视频介绍片段。该模块名为 VideoIntroductionClipCut&#xff0c;用户可以通过该工具快速进行视频的混剪和介绍内容的生…

Selenium元素定位:深入探索与实践

目录 一、引言 二、Selenium元素定位基础 1. WebDriver与元素定位 2. 定位策略概览 三、ID定位 1. 特点与优势 2. 示例代码 四、Class Name定位 1. 特点与限制 2. 示例代码 五、XPath定位 1. 特点与优势 2. 示例代码 3. XPath高级用法 六、CSS Selector定位 1.…

Nacos 服务注册与发现

目录 Nacos 简介 Nacos(Dynamic Naming and Configuration Service) Nacos 安装 下载安装包 Windows 解压 目录介绍: 修改单机模式 启动 Nacos Linux 解压 单机模式启动 Nacos 快速上手 服务注册和发现 Nacos 负载均衡 服务下线 权重配置 开启 Nacos 负载均衡…

LeetCode --- 139双周赛

题目列表 3285. 找到稳定山的下标 3286. 穿越网格图的安全路径 3287. 求出数组中最大序列值 3288. 最长上升路径的长度 一、找到稳定山的下标 遍历数组&#xff0c;统计符合要求的答案即可&#xff0c;代码如下 class Solution { public:vector<int> stableMountai…

【开源免费】基于SpringBoot+Vue.JS服装商城系统(JAVA毕业设计)

本文项目编号 T 046 &#xff0c;文末自助获取源码 \color{red}{T046&#xff0c;文末自助获取源码} T046&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 新…

【C++】仿函数

&#x1f525;个人主页&#x1f525;&#xff1a;孤寂大仙V &#x1f308;收录专栏&#x1f308;&#xff1a;C从小白到高手 &#x1f339;往期回顾&#x1f339;&#xff1a;【C】list常见用法 &#x1f516; 流水不争&#xff0c;争的是滔滔不息。 文章目录 一、仿函数的介绍…