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

news2024/9/21 2:43:24

思维导图

目录

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.coloradmin.cn/o/2145426.html

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

相关文章

信息安全数学基础(18)模重复平方计算法

前言 模重复平方计算法(Modular Exponentiation by Squaring),也称为快速幂算法,是一种用于高效计算 abmodn 的算法,其中 a、b 和 n 是整数,且 b 可能非常大。这种算法通过减少乘法操作的次数来加速计算过程…

伦敦金的交易差价意味着什么?

在伦敦金投资市场上,点差是指交易平台的买入价(买价)和卖出价(卖价)之间的差额。对投资者来说,点差是交易成本的一部分,但它是经纪商的收入来源。点差代表伦敦金投资者在进入和退出交易时需要支…

Python 入门教程(4)数据类型 | 4.5、字符串类型

文章目录 一、字符串类型1、字符串的定义2、字符串索引3、字符串的基本操作4、字符串的编码5、字符串的不可变性6、总结 前言: 在Python中,字符串(String)是一种非常重要的数据类型,用于表示和存储文本信息。Python的字…

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

本教程基于自研的AI工具箱Tauri版进行VideoIntroductionClipCut视频介绍混剪。 进入软件后可以直接搜索 VideoIntroductionClipCut 或者依次点击 Python音频技术/视频tools 进入该模块。 视频样片《Tara音乐介绍》 《我的AI工具箱Tauri版-VideoIntroductionClipCut视频介绍混…

excel VBA进行间比法设计

在品比试验大家多使用间比法试验设计,这里通过excel VBA实现间比法设计,代码如下: Sub 生成试验设计()Dim ws As Worksheet Dim rng As Range, rng2 As Range, rng3 As Range Dim cell As Range, lastcell As Range Dim rd As String, sn As…

SpringBootWeb增删改查入门案例

前言 为了快速入门一个SpringBootWeb项目,这里就将基础的增删改查的案例进行总结,作为对SpringBootMybatis的基础用法的一个巩固。 准备工作 需求说明 对员工表进行增删改查操作环境搭建 准备数据表 -- 员工管理(带约束) create table emp (id int …

论文阅读 | 基于流模型和可逆噪声层的鲁棒水印框架(AAAI 2023)

Flow-based Robust Watermarking with Invertible Noise Layer for Black-box DistortionsAAAI, 2023,新加坡国立大学&中国科学技术大学本论文提出一种基于流的鲁棒数字水印框架,该框架采用了可逆噪声层来抵御黑盒失真。 一、问题 基于深度神经网络…

spring boot admin集成,springboot2.x集成监控

服务端&#xff1a; 1. 新建monitor服务 pom依赖 <!-- 注意这些只是pom的核心东西&#xff0c;不是完整的pom.xml内容&#xff0c;不能直接使用&#xff0c;仅供参考使用 --><packaging>jar</packaging><dependencies><dependency><groupId&g…

STM32 芯片启动过程

目录 一、前言二、STM32 的启动模式三、STM32 启动文件分析1、栈 Stack2、堆 Heap3、中断向量表 Vectors3.1 中断响应流程 4、复位程序 Reset_Handler5、中断服务函数6、用户堆栈初始化 四、STM32 启动流程分析1、初始化 SP、PC 及中断向量表2、设置系统时钟3、初始化堆栈并进入…

【Linux】POSIX信号量与、基于环形队列实现的生产者消费者模型

目录 一、POSIX信号量概述 信号量的基本概念 信号量在临界区的作用 与互斥锁的比较 信号量的原理 信号量的优势 二、信号量的操作 1、初始化信号量&#xff1a;sem_init 2、信号量申请&#xff08;P操作&#xff09;&#xff1a;sem_wait 3、信号量的释放&#xff08…

树——数据结构

这次我来给大家讲解一下数据结构中的树 1. 树的概念 树是一种非线性的数据结构&#xff0c;它是由n(n>0&#xff09;个有限结点组成一个具有层次关系的集合。 叫做树的原因&#xff1a;看起来像一棵倒挂的树&#xff0c;根朝上&#xff0c;叶朝下。 特殊结点&#xff1a…

Vim编辑器常用命令

目录 一、命令模式快捷键 二、编辑/输入模式快捷键 三、编辑模式切换到命令模式 四、搜索命令 一、命令模式快捷键 二、编辑/输入模式快捷键 三、编辑模式切换到命令模式 四、搜索命令

深圳铨顺宏科技展邀您体验前沿人工智能技术

我们诚挚地邀请您参加即将举行的展会&#xff0c;探索RFID技术在资产与人员管理中的广泛应用。这些展会将为您提供一个深入了解前沿技术和创新解决方案的机会。 东莞台湾名品博览会&#xff08;东莞台博会&#xff09;展会时间&#xff1a;9月5日至8日。此次展会展示了来自台湾…

路由器全局配置DHCP实验简述

一、路由器配置 reset saved-configuration Warning: The action will delete the saved configuration in the device. The configuration will be erased to reconfigure. Continue? [Y/N]:y Warning: Now clearing the configuration in the device. Info: Succeeded in c…

如何配置 Apache 反向代理服务器 ?

将 Apache 配置为反向代理意味着将 Apache 设置为侦听和引导 web 流量到后端服务器或服务。这有助于管理和平衡服务器上的负载&#xff0c;提高安全性&#xff0c;并使您的 web 服务更高效。您还可以将其设置为监听标准 HTTP 和 HTTPS 端口上的请求&#xff0c;并将其重定向到运…

基于Leaflet和天地图的直箭头标绘实战-源码分析

目录 前言 一、Leaflet的特种标绘库 1、特种标绘对象的定义 2、Plot基类定义 3、直线箭头的设计与实现 二、在天地图中进行对象绘制 1、引入天地图资源 2、标绘对象的调用时序 3、实际调用过程 三、总结 前言 在博客中介绍过geoman标绘的具体实现&#xff0c;使用Leaf…

Linux驱动开发 ——架构体系

只读存储器&#xff08;ROM&#xff09; 1.作用 这是一种非易失性存储器&#xff0c;用于永久存储数据和程序。与随机存取存储器&#xff08;RAM&#xff09;不同&#xff0c;ROM中的数据在断电后不会丢失&#xff0c;通常用于存储固件和系统启动程序。它的内容在制造时或通过…

教师薪酬管理系统的设计与实现

摘 要 传统信息的管理大部分依赖于管理人员的手工登记与管理&#xff0c;然而&#xff0c;随着近些年信息技术的迅猛发展&#xff0c;让许多比较老套的信息管理模式进行了更新迭代&#xff0c;老师信息因为其管理内容繁杂&#xff0c;管理数量繁多导致手工进行处理不能满足广…

【专题】2024中国生物医药出海现状与趋势蓝皮书报告合集PDF分享(附原数据表)

原文链接&#xff1a;https://tecdat.cn/?p37719 出海已成为中国医药产业实现提速扩容的重要途径。目前&#xff0c;中国医药产业发展态势良好&#xff0c;创新能力不断增强&#xff0c;然而也面临着医保政策改革和带量集采带来的压力。政府积极出台多项政策支持医药企业出海…

人工智能 | 基于ChatGPT开发人工智能服务平台

简介 ChatGPT 在刚问世的时候&#xff0c;其产品形态就是一个问答机器人。而基于ChatGPT的能力还可以对其做一些二次开发和拓展。比如模拟面试功能、或者智能机器人功能。 模拟面试功能包括个性化问题生成、实时反馈、多轮面试模拟、面试报告。 智能机器人功能提供24/7客服支…