JVM-垃圾回收

目录

1、GC过程

2、垃圾回收算法

2.1、标记-清除

2.2、标记-整理

2.3、复制

2.4、分代收集算法

3、TLAB

4、对象如何进入老年代

5、卡片标记

6、HotSpot垃圾回收器

6.1、年轻代垃圾回收器

6.2、老年代垃圾回收器

6.3、如何配置垃圾回收器

6.4、STW

7、CMS垃圾回收器

7.1、定义

7.2、设计目标

7.3、CMS回收过程

7.4、内存碎片

7.5、CMS的停顿(STW)

7.6、CMS缺点

8、G1垃圾回收器

8.1、为什么需要G1?

8.2、G1的设计目标

8.3、CMS和G1的区别?

8.4、G1 有年轻代和老年代的区分吗?

8.5、G1的优点

8.6、G1的数据结构

8.8、G1的垃圾回收过程

8.8.1、年轻代回收(STW)

8.8.2、并发标记

8.8.3、混合回收(Mixed GC)

9、ZGC


1、GC过程

        先找到活跃的对象,然后把其他不活跃的对象判定为垃圾,然后删除。所以垃圾回收只与活跃的对象有关,和堆的大小无关。

2、垃圾回收算法

2.1、标记-清除

        标记存活的对象,然后将未标记的对象统一清除。缺点是会产生内存碎片。

2.2、标记-整理

        标记存活的对象,然后把整个堆中未标记的对象压缩到堆的其中一块,从而避免了内存的碎片化问题。

2.3、复制

        将内存一分为二,每次只使用其中一半,满了之后将存活的对象复制到另一半内存中,然后将剩下的碎片一次性擦除。缺点是需要两倍的内存空间。

2.4、分代收集算法

  • 新生代:复制。(新生代存活对象少,复制代价小)
  • 老年代:标记清除,标记整理

年轻代 = 1*Eden + 2*survivor

当年轻代中的 Eden 区分配满的时候,就会触发年轻代的 GC(Minor GC)。具体过程如下:
1、在 Eden 区执行了第一次 GC 之后,存活的对象会被移动到其中一个 Survivor 分区(以下简称from);
2、Eden 区再次 GC,这时会采用复制算法,将 Eden 和 from 区一起清理。存活的对象会被复制到 to 区;接下来,只需要清空 from 区就可以了。

所以在这个过程中,总会有一个 Survivor 分区是空置的。Eden、from、to 的默认比例是 8:1:1,所以只会造成 10% 的空间浪费。( -XX:SurvivorRatio 进行配置的(默认为 8))

3、TLAB

        Thread Local Allocation Buffer,JVM 默认给每个线程开辟一个 buffer 区域,用来加速对象分配。这个 buffer 就放在 Eden 区中。

        对象的分配优先在 TLAB上 分配,但 TLAB 通常都很小,所以对象相对比较大的时候,会在 Eden 区的共享区域进行分配。

4、对象如何进入老年代

  • 提升

        对象在新生代的GC存活次数阈值:‐XX:+MaxTenuringThreshold(最大为15)。即一个对象,在15次GC后,依然存活,那么将该对象提升到老年代。

  • 分配担保

        当 Survivor 空间不够,就需要依赖其他内存(指老年代)进行分配担保。这个时候,对象也会直接在老年代上分配。

  • 大对象直接分配到老年代
  • 动态对象年龄判断

        比如,如果幸存区中相同年龄对象大小的和,大于幸存区的一半,大于或等于 age 的对象将会直接进入老年代。

5、卡片标记

        老年代是被分成众多的卡页(card page)的(一般数量是 2 的次幂)。

        卡表(Card Table)就是用于标记卡页状态的一个集合,每个卡表项对应一个卡页。

        如果年轻代有对象分配,而且老年代有对象指向这个新对象, 那么这个老年代对象所对应内存的卡页,就会标识为 dirty,卡表只需要非常小的存储空间就可以保留这些状态。

        垃圾回收时,就可以先读这个卡表,进行快速判断。

6、HotSpot垃圾回收器

6.1、年轻代垃圾回收器

  • Serial:单线程,垃圾回收时暂停用户线程,复制算法。
  • ParNew:多线程,垃圾回收时暂停用户线程。追求降低用户停顿时间,适合交互式应用。强交互弱计算。
  • Parallel Scavenge:多线程垃圾回收器,追求 CPU 吞吐量,能够在较短时间内完成指定任务,适合没有交互的后台计算。弱交互强计算。

6.2、老年代垃圾回收器

  • Serial Old:单线程,垃圾回收时暂停用户线程,标记-整理算法。
  • Parallel Old:Parallel Scavenge 的老年代版本,追求 CPU 吞吐量。
  • CMS:垃圾回收和用户线程并发执行。以获取最短 GC 停顿时间为目标的收集器,它在垃圾收集时使得用户线程和 GC 线程能够并发执行,因此在垃圾收集过程中用户也不会感到明显的卡顿。

6.3、如何配置垃圾回收器

  • -XX:+UseSerialGC 年轻代和老年代都用串行收集器
  • -XX:+UseParNewGC 年轻代使用 ParNew,老年代使用 Serial Old
  • -XX:+UseParallelGC 年轻代使用 ParallerGC,老年代使用 Serial Old
  • -XX:+UseParallelOldGC 新生代和老年代都使用并行收集器
  • -XX:+UseConcMarkSweepGC,表示年轻代使用 ParNew,老年代的用 CMS
  • -XX:+UseG1GC 使用 G1垃圾回收器
  • -XX:+UseZGC 使用 ZGC 垃圾回收器

6.4、STW

        Stop the world,在垃圾回收时,暂停用户的一切线程。垃圾回收器是为了让GC时间更短,减少停顿,并不能完全消除停顿。

7、CMS垃圾回收器

7.1、定义

  • 并发标记清除垃圾收集器
  • 年轻代:复制算法
  • 老年代:并发标记-清除算法

7.2、设计目标

  • 避免在老年代 GC 时出现长时间的卡顿。
  • 它把最耗时的一些操作,做成了和应用线程并行。

7.3、CMS回收过程

初始标记(STW状态:(时间短))
        1、标记直接关联GC ROOT的对象;
        2、标记年轻代中对象的引用。

并发标记(并行)
        1、标记所有可达的对象,耗时长,但可与用户线程并行执行。
        2、将老年代中发生变化的卡页,标记为dirty状态。

并发预清理(并行)
        1、重新标记老年代中状态为dirty的卡页,并清除掉dirty的状态;
        2、将老年代中发生变化的卡页,标记为dirty状态。

并发可取消的预清理(可选)(并行)
        在满足某些条件的时候,可以终止,比如迭代次数、有用工作量、消耗的系统时间等。

最终标记(SWT)
        完成老年代中所有存活对象的标记。(处理老年代中的所有状态为dirty的卡页,且不会再增加新的dirty状态的卡页)

并发清除(并发)
        删除不可达对象,并回收空间。(新产生的垃圾对象留待下次GC处理,被称作浮动垃圾)

并发重置(并发)
        重置 CMS 算法相关的内部数据,为下一次 GC 循环做准备。

7.4、内存碎片

一般情况下,当老年代的使用率达到 70%,就会触发 GC。
可通过参数 -XX:CMSInitiatingOccupancyFraction 用来配置这个比例。

CMS 对老年代回收时,并没有内存的整理阶段。所以,CMS提供了两个参数来解决这个问题:

  • UseCMSCompactAtFullCollection(默认开启):表示在要进行 Full GC 的时候,进行内存碎片整理。内存整理的过程是无法并发的,所以停顿时间会变长。
  • CMSFullGCsBeforeCompaction:每隔多少次不压缩的 Full GC 后,执行一次带压缩的 Full GC。默认值为 0,表示每次进入 Full GC 时都进行碎片整理。

7.5、CMS的停顿(STW)

  1. 初始标记,这部分的停顿时间较短;
  2. Minor GC(可选),在预处理阶段对年轻代的回收,停顿由年轻代决定;
  3. 重新标记,由于 preclaen 阶段的介入,这部分停顿也较短;
  4. Serial-Old 收集老年代的停顿,主要发生在预留空间不足的情况下,时间会持续很长;
  5. Full GC,永久代空间耗尽时的操作,由于会有整理阶段,持续时间较长。

7.6、CMS缺点

  1. CPU敏感:并发标记、清除过程中因占用一部分线程可能导致应用程序变慢。
  2. 并发清除过程中会产生浮动垃圾。
  3. 标记清除算法会存在空间碎片的情况。

8、G1垃圾回收器

8.1、为什么需要G1?

        CMS在发生 Minor GC 时,由于 Survivor 区已经放不下了,多出的对象只能提升(promotion)到老年代。但是此时老年代因为空间碎片的缘故,会发生 concurrent mode failure 的错误。这个时候,就需要降级为 Serail Old 垃圾回收器进行收集。

8.2、G1的设计目标

        分而治之,部分收集。

        在任意 1 秒的时间内,停顿不得超过 10ms。-XX:MaxGCPauseMillis=10。(控制STW时间)

8.3、CMS和G1的区别?

  • CMS回收器,是对某个年代的整体收集,无法控制收集时间;
  • G1回收器,把堆分成了很多份,把每一份当做一个小目标,控制收集时间。

8.4、G1 有年轻代和老年代的区分吗?

G1堆内存划分
  • G1也会分年轻代和老年代,只不过它们在内存上是不连续的,而是由一小份一小份(Region)组成,被称作小堆区。
  • 对象超过Region大小的50%,会被分配到黄色区域,被称作Humongous Region(连续的小堆区)。
  • 可通过-XX:G1HeapRegionSize=<N>M设置Region大小。
  • 垃圾回收的时候,会优先回收垃圾最多的小堆区。

8.5、G1的优点

  • 任意1秒内停顿时间不会超过10ms;
  • 停顿时间不会随着堆的增大而增大;
  • 复制算法和标记整理算法,保证无空间碎片问题。

8.6、G1的数据结构

Rset

  • 用于记录和维护Region之间的对象引用关系。
  • 把 RSet 理解成一个 Hash,key 是引用的 Region 地址,value 是引用它的对象的卡页集合。
  • 年轻代的Rset:只保存来自老年代的引用,因为年轻代的回收是针对所有年轻代Region;
  • 老年代的Rset:只保存老年代对它的引用,因为老年代回收之前,会先对年轻代进行垃圾回收。

CSet

        收集集合,保存一次GC中将执行垃圾回收的区间(Region)。

8.8、G1的垃圾回收过程

8.8.1、年轻代回收(STW)

Minor GC,Eden区满的时候,会发生年轻代的垃圾回收。
跨代引用使用 RSet 数据结构来追溯,会一次性回收掉年轻代的所有 Region。

  1. 扫描根:根,可以看作是我们前面介绍的 GC Roots,加上 RSet 记录的其他 Region 的外部引用。
  2. 更新RSet:RSet 可以准确的反映老年代对所在的内存分段中对象的引用。
  3. 处理RSet:识别被老年代对象指向的 Eden 中的对象,这些被指向的 Eden 中的对象被认为是存活的对象。
  4. 复制对象:Eden 区内存段中存活的对象会被复制到 Survivor 区中空的 Region。
  5. 处理引用:处理 Soft、Weak、Phantom、Final、JNI Weak 等引用。结束收集。

8.8.2、并发标记

当整个堆内存使用达到一定比例(默认是 45%),并发标记阶段就会被启动。
可通过参数 -XX:InitiatingHeapOccupancyPercent 进行配置。

  1. 初始标记(STW):GC ROOT扫描
  2. Root 区扫描:扫描对老年代的引用,并标记被引用的对象。
  3. 并发标记:从 GC Roots 开始对 heap 中的对象标记,标记线程与应用程序线程并行执行,并且收集各个 Region 的存活对象信息。
  4. 重新标记(STW):标记那些在并发标记阶段发生变化的对象。
  5. 清理阶段:如果发现 Region 里全是垃圾,在这个阶段会立马被清除掉。不全是垃圾的 Region,并不会被立马处理,它会在 Mixed GC 阶段,进行收集。

8.8.3、混合回收(Mixed GC)

        在 Minor GC 之后,如果判断这个占比达到了某个阈值(垃圾占比),下次就会触发 Mixed GC。这个阈值,由 -XX:G1HeapWastePercent 参数进行设置(默认是堆大小的 5%)。

9、ZGC

  • 停顿时间不会超过 10ms;
  • 停顿时间不会随着堆的增大而增大(不管多大的堆都能保持在 10ms 以下);
  • 可支持几百 M,甚至几 T 的堆大小(最大支持 4T)。
  • 连逻辑上的年轻代和老年代也去掉了,只分为一块块的 page,每次进行 GC 时,都会对 page 进行压缩操作,所以没有碎片问题。

以上内容为个人学习理解,如有问题,欢迎在评论区指出。

部分内容截取自网络,如有侵权,联系作者删除。

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

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

相关文章

【漏洞复现】Apache_Tomcat7+ 弱口令 后台getshell漏洞

感谢互联网提供分享知识与智慧&#xff0c;在法治的社会里&#xff0c;请遵守有关法律法规 文章目录 1.1、漏洞描述1.2、漏洞等级1.3、影响版本1.4、漏洞复现1、基础环境2、漏洞扫描3、漏洞验证 说明内容漏洞编号漏洞名称Tomcat7 弱口令 && 后台getshell漏洞漏洞评级高…

SpringBoot整合EasyExcel

springboot整合easyExcel的全流程&#xff0c;跟着做就能出来。对项目没有侵入要求。0侵入&#xff0c;可插拔 依赖 <!--操作Excel依赖--><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>…

linux下实现电脑开机后软件自启动

实现linux的软件自启动&#xff0c;需要四个文件 第一个【displayScreen.desktop】文件&#xff0c;.desktop文件就是一个用来运行程序的快捷方式,也叫启动器&#xff0c;常用来自启动用的文件&#xff0c;内容如下 [Desktop Entry] #要执行的脚本位置 Exec/home/yicaobao/te…

offsetof宏的使用、模拟实现及 (size_t)(((struct_type*)0)->mem_name)的解释

宏原型&#xff1a;offsetof(type,member) 作用&#xff1a;返回数据结构或联合体类型中成员的偏移量&#xff0c;以字节为单位 返回值&#xff1a;size_t类型的无符号整数 使用案例&#xff1a; #include <stdio.h> #include <stddef.h> struct foo {ch…

Unity热更新那些事

目录 热更新方案Unity程序的两种编译方式编译阶段执行阶段Mono方式IL2CPP方式两种方式打包以后的项目目录结构 其他 ILRuntime热更新ILRuntime使用注意ILRuntime的实现原理ILRuntime的性能优化建议ILRuntime的性能优化建议 HybridCLR热更新 参考链接 Unity热更新那些事 一小时极…

pda条码二维码扫描数据采集安卓手持终端扫码热敏标签打印一体机

HT800新一代移动物联终端是深圳联强优创信息科技有限公司自主研发的基于Android11操作系统的高性能、高可靠的工业级手持数据终端&#xff0c;能与其它设备进行无线通讯&#xff0c;提供良好的操作界面&#xff0c;支持条码扫描、RFID读写&#xff08;NFC&#xff09;、GPS定位…

Android 扩大View可点击区域范围

有时候会遇到这种需求&#xff1a;本身控件显示在很小的范围内&#xff0c;但是要求扩大可点击的区域。根据官方文档https://developer.android.com/develop/ui/views/touch-and-input/gestures/viewgroup?hlzh-cn#delegate可以得知通过 TouchDelegate 类&#xff0c;让父视图…

【复盘】记录一次JVM 异常问题 java.lang.OutOfMemoryError: unable to create new native thread

背景是最新运营提了一个需求&#xff0c;需要根据用户信息拉去三分机构的信贷数据&#xff0c;需要达到一天百万级别&#xff0c;但是经过实际测试&#xff0c;也只能达到40W量级&#xff0c;具体就是通过起多个Spring Boot项目&#xff0c;每个项目1S拉一个用户&#xff0c;基…

使用 Rust 进行程序

首先&#xff0c;我们需要安装必要的库。在终端中运行以下命令来安装 scraper 和 reqwest 库&#xff1a; rust cargo install scraper reqwest 然后&#xff0c;我们可以开始编写程序。以下是一个基本的爬虫程序&#xff0c;用于爬取 上的图片&#xff1a; rust use reqwe…

接口自动化测试分层设计与实践总结01

本文以笔者当前使用的自动化测试项目为例&#xff0c;浅谈分层设计的思路&#xff0c;不涉及到具体的代码细节和某个框架的实现原理&#xff0c;重点关注在分层前后的使用对比&#xff0c;可能会以一些伪代码为例来说明举例。 接口测试三要素&#xff1a; 参数构造 发起请求&…

C#,数值计算——偏微分方程,Relaxation的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { public class Relaxation { private Relaxation() { } public static void sor(double[,] a, double[,] b, double[,] c, double[,] d, double[,] e, double[,] f, double[,] u, double rjac) …

Python基础(第五期): python数据容器(序列) 列表 集合 元素 字符串 字典 序列遍历操作

python基础专栏 python基础&#xff08;第五期&#xff09; 文章目录 python基础&#xff08;第五期&#xff09;数据容器一、列表1、列表的定义2、列表的下标索引 3、列表的(添加)方法3.1 列表的查询方法3.2 修改特定下标索引的值3.3 列表指定位置插入元素3.3 列表指定元素的追…

Elasticsearch:搜索架构

Elasticsearch 全文检索的复杂性 为了理解为什么全文搜索是一个很难解决的问题&#xff0c;让我们想一个例子。 假设你正在托管一个博客发布网站&#xff0c;其中包含数亿甚至数十亿的博客文章&#xff0c;每个博客文章包含数百个单词&#xff0c;类似于 CSDN。 执行全文搜索…

【Unity细节】为什么UI移动了锚点,中心点和位置,运行的时候还是不在设置的位置当中

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 秩沅 原创 &#x1f636;‍&#x1f32b;️收录于专栏&#xff1a;unity细节和bug &#x1f636;‍&#x1f32b;️优质专栏 ⭐【…

数据约束及增删改查(CRUD)进阶-MySQL

文章目录 一、数据库约束1.1 约束类型1.2 NULL约束1.3 UNIQUE&#xff1a;唯一约束1.4 DEFAULT&#xff1a;默认值约束1.5 PRIMARY KEY&#xff1a;主键约束1.6 FOREIGN KEY&#xff1a;外键约束1.7 CHECK 约束&#xff08;了解&#xff09; 二、表的设计2.1 一对一2.2 一对多2…

kimera论文阅读

功能构成&#xff1a; Kimera包括四个关键模块: Kimera-VIO的核心是基于gtsam的VIO方法[45]&#xff0c;使用IMUpreintegration和无结构视觉因子[27]&#xff0c;并在EuRoC数据集上实现了最佳性能[19]; Kimera-RPGO:一种鲁棒姿态图优化(RPGO)方法&#xff0c;利用现代技术进…

代码随想录 Day38 完全背包问题 LeetCode T70 爬楼梯 T322 零钱兑换 T279 完全平方数

前言 在今天的题目开始之前,让我们来回顾一下之前的知识,动规五部曲 1.确定dp数组含义 2.确定dp数组的递推公式 3.初始化dp数组 4.确定遍历顺序 5.打印dp数组来排错 tips: 1.当求取物品有限的时候用0-1背包,求取物品无限的时候用完全背包 结果是排列还是组合也有说法,当结果是组…

vue 实现在线预览Excel-LuckyExcel/LuckySheet实现方案

一、准备工作 1. npm安装 luckyexcel npm i -D luckyexcel 2.引入luckysheet 注意&#xff1a;引入luckysheet&#xff0c;只能通过CDN或者直接引入静态资源的形式&#xff0c;不能npm install。 个人建议直接下载资源引入。我给你们提供一个下载资源的地址&#xff1a; …

JVM虚拟机:垃圾回收器之Parallel Scavenge

本文重点 在前面的课程中,我们学习了新生代的串行化垃圾回收器Serial,本文我们将学习新生代的另外一个垃圾回收器Parallel Scavenge(PS),PS是一个并行化的垃圾回收器,它使用复制算法来清理新生代的垃圾。 运行方式 如上所示,当进行垃圾回收的时候,它会暂停工作线程,而…