【JAVAEE】JVM中垃圾回收机制 GC

 

  • 博主简介:想进大厂的打工人
  • 博主主页:@xyk:
  • 所属专栏: JavaEE初阶 

上篇文章我们讲了java运行时内存的各个区域。

传送门:【JavaEE】JVM的组成及类加载过程_xyk:的博客-CSDN博客

对于程序计数器、虚拟机栈、本地方法栈这三部分区域而言,其生命周期与相关线程有关,随线程而生,随线程而灭。并且这三个区域的内存分配与回收具有确定性,因为当方法结束或者线程结束时,内存就自然跟着线程回收了。因此我们本篇所讲的有关内存分配和回收关注的为Java堆与方法区这两个区域。


目录

文章目录

一、垃圾回收机制—GC

1.1 引用计数器算法(java没有采用这种算法)

1.2 可达性分析

二、垃圾回收算法

2.1 标记清除算法

2.2 复制算法

2.3 标记整理算法

2.4 复合策略”分带回收“

三、垃圾收集器

3.1 CMS收集器(老年代收集器,并发GC)

3.2 G1收集器(唯一一款全区域的垃圾回收器)


一、垃圾回收机制—GC

在JVM中存在一个垃圾回收机制,GC,帮助程序猿自动释放内存的,能够有效的减少内存泄漏的出现频率。主要是针对 堆上的对象 来进行释放~

GC也就是以 对象 为单位进行释放的(说是释放内存,其实是释放对象)

GC中主要分成两个阶段:

1.找,谁是垃圾

2.释放,用什么算法

Java堆中存放着几乎所有的对象实例,垃圾回收器在对堆进行垃圾回收前,首先要判断这些对象哪些还存活,哪些已经"死去"。判断对象是否已"死"有如下几种算法

死亡对象的判断算法:

1.1 引用计数器算法(java没有采用这种算法)

引用计算器判断对象是否存活的算法是这样的:给每一个对象设置一个引用计数器,每当有一个地方引用这个对象的时候,计数器就加1,与之相反,每当引用失效的时候就减1。当计数器为0,则认为没有对象了,就是垃圾了~

优点:实现简单、性能高。

缺点:增减处理频繁消耗cpu计算、计数器占用很多位浪费空间(每个对象都需要分配一个计数器)、最重要的缺点是无法解决循环引用的问题。

什么是循环引用?

存在两个对象,同时互相引用指向对象

 

此时,如果a和b都销毁了,这个时候,两个对象的引用计数给自减1,但是这两个对象的引用计数不是0,不能作为垃圾,无法回收,这俩个对象也无法使用了~陷入了一个逻辑上的循环

1.2 可达性分析

把对象之间的引用关系,理解成了一个树形结构,从一些特殊的起点出发,进行遍历,只要能遍历访问到的对象,就是”可达“,再把”不可达的“当作垃圾回收即可

通过 root 这个引用,就可以访问到整个树的任意结点,那么哪些对象可以作为gcroot?

  1. 栈上的局部变量(每个栈的每个局部变量,都是起点)
  2. 常量池中的引用的对象
  3. 方法区中,静态成员引用的对象

可达性分析,克服了引用计数的两个缺点~

但是也有自己的问题:

1.消耗更多的时间,因此某个对象成了垃圾,也不一定第一时间发现,每次扫描的过程,都是需要消耗时间的

2.在进行可达性分析的时候,要顺藤摸瓜,一旦这个过程中,代码的对象引用关系发生变化了,就麻烦了

因为,为了更准确的完成这个”摸瓜“的过程,需要让其他的业务线程 暂停工作!!(STW问题

stop the world,为了保证内存的一致性,必须先暂停程序的执行)

二、垃圾回收算法

上面我们可以通过可达性分析找到垃圾,那么我们应该用什么回收算法来进行回收操作呢?

2.1 标记清除算法

标记-清除算法是最基础的算法,像它的名字一样算法分为“标记”和“清除”两个阶段,首先需要标记出所需要回收的对象,标记完成后统一收集被标记的对象。

优点: 实现简单。

缺点: 产生不连续的内存碎片;“标记”和“清除”的执行效率都不高。如果要申请空间比较大,会失败。

2.2 复制算法

"复制"算法是为了解决"标记-清理"的效率问题。它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这块内存需要进行垃圾回收时,会将此区域还存活着的对象复制到另一块上面,然后再把已经使用过的内存区域一次清理掉。

 

优点: 执行效率高。

缺点: 空间利用率低, 因为复制算法每次只能使用一半的内存。

2.3 标记整理算法

类似于 顺序表删除中间元素,有一个搬运过程~
 

优点: 解决了内存碎片问题,比复制算法空间利用率高。

缺点: 因为有局部对象移动,相对效率不高。

2.4 复合策略”分带回收“

因此,实际上 JVM 的实现思路,是结合了上述几种思想方法,针对不同的情况,使用不同的策略.

给对象设定了”年龄“这样的概念,描述了这个对象存在多久了,如果一个对象刚诞生,认为是0岁,每次经过一轮扫描,没被标记成垃圾,这个时候对象就涨一岁,通过年龄来区分这个对象的 存活时间

1.新创建的对象,放到伊甸区,当垃圾回收扫描伊甸区之后,绝大部分对象都会在第一轮 GC 中就被干掉~~ 大部分对象是活不过一岁的,朝生夕死

2.如果伊甸区的对象,熬过第一轮 GC ,就会通过复制算法,拷贝到幸存区,幸存区分成两半大小,一次只使用其中的一半~~ 垃圾回收扫描幸存区的对象,也是发现垃圾就淘汰,不是垃圾的,通过复制算法,复制到幸存区的另外一半

3.当这个对象在幸存区,熬过若干轮 GC 之后,年龄增长到一定程度了,就会通过复制算法拷贝到老年代

4.进入老年代的对象,年龄都很大了,再消亡的概率比前面新生代中的对象小,针对老年代 GC 的扫描频次就会降低很多,如果老年代发现某个对象是垃圾了,使用标记整理的方式清除

5.特殊情况,如果对象非常大,直接进入老年代(大对象进行复制算法,成本比较高,而且大对象也不会很多)

三、垃圾收集器

3.1 CMS收集器(老年代收集器,并发GC)

特性:
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。目前
很大一部分的Java应用集中在互联网站或者B/S系统的服务端上,这类应用尤其重视服务的响应速
度,希望系统停顿时间最短,以给用户带来较好的体验。CMS收集器就非常符合这类应用的需求。
CMS收集器是基于“标记—清除”算法实现的,它的运作过程相对于前面几种收集器来说更复杂一些,整个过程分为4个步骤:

初始标记(CMS initial mark)
初始标记仅仅只是标记一下GC Roots能直接关联到的对象,速度很快,需要“Stop The
World”。


并发标记(CMS concurrent mark)
并发标记阶段就是进行GC Roots Tracing的过程。


重新标记(CMS remark)
重新标记阶段是为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分
对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的
时间短,仍然需要“Stop The World”。


并发清除(CMS concurrent sweep)
并发清除阶段会清除对象

由于整个过程中耗时最长的并发标记和并发清除过程收集器线程都可以与用户线程一起工作,所以,从总体上来说,CMS收集器的内存回收过程是与用户线程一起并发执行的

缺点:

  1. CMS收集器对CPU资源非常敏感
  2. CMS收集器无法处理浮动垃圾 
  3. CMS收集器会产生大量空间碎片

 

3.2 G1收集器(唯一一款全区域的垃圾回收器)

G1(Garbage First)垃圾回收器是用在heap memory很大的情况下,把heap划分为很多很多的
region块,然后并行的对其进行垃圾回收

G1垃圾回收器回收region(区域)的时候基本不会STW,而是基于 most garbage优先回收(整体来看是基于"标记-整理"算法,从局部(两个region之间)基于"复制"算法) 的策略来对region进行垃圾回收的。

一个region有可能属于Eden,Survivor或者Tenured内存区域。图中的E表示该region属于Eden内存区域,S表示属于Survivor内存区域,T表示属于Tenured内存区域。图中空白的表示未使用的内存空间。G1垃圾收集器还增加了一种新的内存区域,叫做Humongous内存区域,如图中的H块。这种内存区域主要用于存储大对象-即大小超过一个region大小的50%的对象

1.年轻代垃圾收集
在G1垃圾收集器中,年轻代的垃圾回收过程使用复制算法。把Eden区和Survivor区的对象复制到新的Survivor区域

 2.老年代垃收集

1.初始标记(Initial Mark)阶段 - 同CMS垃圾收集器的Initial Mark阶段一样,G1也需要暂停应用程序的执行,它会标记从根对象出发,在根对象的第一层孩子节点中标记所有可达的对象。

2.并发标记(Concurrent Mark)阶段 - 在这个阶段G1做的事情跟CMS一样。但G1同时还多做了一件事情,就是如果在Concurrent Mark阶段中,发现哪些Tenured region中对象的存活率
很小或者基本没有对象存活,那么G1就会在这个阶段将其回收掉,而不用等到后面的clean
up阶段。
 

3.最终标记(CMS中的Remark阶段) - 在这个阶段G1做的事情跟CMS一样, 但是采用的算法不
同,G1采用一种叫做SATB(snapshot-at-the-begining)的算法能够在Remark阶段更快的标
记可达对象。

4.筛选回收(Clean up/Copy)阶段 - 在G1中,没有CMS中对应的Sweep阶段。相反 它有一个
Clean up/Copy阶段,在这个阶段中,G1会挑选出那些对象存活率低的region进行回收,这个
阶段也是和minor gc一同发生的,如下图所示

G1(Garbage-First)是一款面向服务端应用的垃圾收集器。HotSpot开发团队赋予它的使命是未来可以替换掉JDK 1.5中发布的CMS收集器。 如果你的应用追求低停顿,G1可以作为选择;如果你的应用追求吞吐量,G1并不带来特别明显的好处。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

动态规划01背包之1049 最后一块石头的重量 II(第9道)

题目: 有一堆石头,用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。 每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 。那么粉碎的可能结果如下: …

微信小程序(二)

目录 1、input标签 一、表单绑定 1、数据绑定 2、输入获取 二、网络请求 1、介绍 2、注意 3、使用 4、基于Promise封装 三、自定义组件 1、创建 2、父向子组件通信 3、子向父组件通信 4、生命周期 四、vant weapp组件库 1、配置 2、使用 进入本章前的拓展&#…

Git❀详细使用教程

Git❀详细使用教程 一、Git简介1.1 什么是Git?1.2 Git的特点1.3 集中式与分布式的区别?1.4 Git工作流程图 二、Git安装与常用命令2.1 Git环境配置2.1.1 下载与安装2.1.2 基本配置2.1.3 为常用指令设置别名(可选)2.1.4 解决GitBash…

jsonschema networknt json-schema-validator 高级能力json 数字很大时, 变成什么类型

入参校验产品化 schema_个人渣记录仅为自己搜索用的博客-CSDN博客 自动变成了bigInteger类型. 哪怕你的jsonSchema 配置的是integer , 不冲突.

AlGaN基深紫外FP激光器仿真模型及材料信息数据库有何用途?

波长范围为UVC波段(100-280 nm)的深紫外FP(Fabry-Pero,法布里和珀罗是两位法国的科学家)激光器可广泛应用于数据通信、光通信、3D打印、材料加工、显示与照明、激光雷达、人脸/手势识别、医疗和表面监测等领域。FP激光…

2023年Q2京东冰箱行业品牌销售排行榜(京东销售数据分析)

近年我国的冰箱零售呈波动变化的趋势,由于冰箱市场趋于饱和,因此消费者对冰箱的需求逐渐变为替换需求,这也进一步推动了产品的更新迭代。接下来结合具体数据,我们来分析一下2023年Q2冰箱行业的销售详情。 根据鲸参谋电商数据分析平…

SpringBoot+Vue实现的高校图书馆管理系统

项目描述:这是一个基于SpringBootVue框架开发的高校图书馆管理系统。首先,这是一个前后端分离的项目,代码简洁规范,注释说明详细,易于理解和学习。其次,这项目功能丰富,具有一个高校图书馆管理系…

6.2.5 网络基本服务----动态主机配置协议DHCP

6.2.5 网络基本服务----动态主机配置协议DHCP 动态主机配置协议允许一台计算机加入新的网络时可自动获取网络配置信息,不用人工参与。连网的计算机需要配置的参数包括 IP地址子网掩码默认路由器的IP地址域名服务器IP地址 DHCP与DNS、FTP、Telnet一样也采用客户服…

Lua脚本本地调试

这里主要使用日志的方式进行debug 环境依赖 项目对openresty包的依赖比较高,所以环境基础都在openresty下进行 openresty的使用 openresty下载地址 下载完成后解压,具体使用方式和nginx没有什么区别,主要依赖文件是一下几个 nginx.exe …

搬家送货小程序开发源码定制一键报警实时定位路线规划

1.货物信息录入: 用户可以输入货物的名称、数量、重量、尺寸等信息。 2.路线选择: 用户可以选择起始地点和目的地点,并根据需求选择最佳路线。 提供地图服务或第三方路径规划服务,以帮助用户确定最佳路线。 3.车辆选择&#…

基于深度学习的高精度鸡蛋检测识别系统(PyTorch+Pyside6+YOLOv5模型)

摘要:基于深度学习的高精度鸡蛋检测识别系统可用于日常生活中或野外来检测与定位鸡蛋目标,利用深度学习算法可实现图片、视频、摄像头等方式的鸡蛋目标检测识别,另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检测模型…

跨域问题解决

由于同源策略,需要协议,域名,端口三个都相同才能进行访问,是一种浏览器的保护策略 CORS:Cross Origin Resource Sharing SpringBoot 项目中解决跨域 1.在目标方法中加入CrossOrigin注解 2.添加一种过滤器 分别是允许哪些域&#…

ffmpeg2段视频合成一段

查看分辨率 帧率和编码器 ffprobe -v error -select_streams v:0 -show_entries streamcodec_name,width,height,avg_frame_rate -of defaultnoprint_wrappers1 rs2.mp4得到,编码器,分辨率,还有帧率 codec_nameh264 width1920 height1080 avg…

Linux 发行版 Gentoo 存在重大漏洞

网络安全公司 SonarSource 在日前研究中发现,Gentoo Linux 发行版中存在漏洞 CVE-2023-28424,黑客可以利用该漏洞进行 SQL 注入攻击。 研究人员从 GentooLinux 的 Soko 搜索组件中找到了这个漏洞。该漏洞的 CVSS 风险评分为 9.1,属于特别重大…

Flutter 仿抖音、豆瓣、知乎、番茄小说的评论弹窗开发实践

最近用flutter做了一个评论弹窗的功能,本来以为很简单的烂大街的一个功能,结果却遇到了不少的问题,而且这些问题我觉得很有意义,以至于我觉得我如果分享出来可能会对其他人很有帮助。 要做一件事情可能会很容易,但做好…

springboot之配置文件加载

springboot启动流程参考。Springboot总结。本内容主要解析里面的配置文件的加载过程。 springboot资源加载 入口。SpringApplication#run 我们知道,run方法是构建容器的过程。里面有一个方法:prepareEnvironment。用于构建环境组件Environment&#xf…

cocos2d-js中jsc逆向为js

1.下载脚本https://github.com/tablis/jsc-decompile-mozjs-34 2.安装php7以上的版本 ubuntu $ sudo apt install php7.0 mac $ brew install php7.0 windows just google an binary one 查看php安装的版本这里mac电脑为例子: 输入:php -v 只要7以上的版本即可 3.cd到…

http协议(二)

欢迎来到南方有乔木的博客!!! 博主主页:点击点击!戳一戳!! 博主名:南方有乔木呀 博主简介: 一名在校大学生,正在努力学习Java语言编程。穷且意坚,不坠青云…

Go语言基础教程:变量、基本数据类型、输出、注释、运算符、if-else条件判断、函数

文章目录 一、变量的使用1.1 定义变量1.2 常量1.3 变量的赋值与内存相关 二、变量基本类型2.1 有符号整型2.2 无符号整型2.3 string类型2.4 bool类型 三、输出3.1 常用打印功能3.2 格式化输出3.3 内置输出方法与fmt的区别 四、注释五、运算符六、条件语句6.1 基本使用6.2 条件嵌…

ncnn源码阅读(三)----数据结构Mat

文章目录 数据结构Mat成员变量成员方法构造函数1、普通构造函数2、外部数据指针构造函数3、拷贝构造函数和opertor 深拷贝函数类型转换引用计数的实现其他数据操作函数 数据结构Mat 个人认为一个框架中的比较核心的两个点,一个是数据结构,一个任务调度…