JVM-垃圾回收

news2023/12/2 10:45:32

目录

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://nwjs.net/news/1210481.html

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

相关文章

重新思考边缘负载均衡

本文介绍了Netflix在基于轮询的负载均衡的基础上&#xff0c;集成了包括服务器使用率在内的多因素指标&#xff0c;并对冷启动服务器进行了特殊处理&#xff0c;从而优化了负载均衡逻辑&#xff0c;提升了整体业务性能。原文: Rethinking Netflix’s Edge Load Balancing[1] 我…

lazarus:数据集快速导出为excel、csv、sql及其他多种格式

lazarus被成为快速开发工具&#xff0c;为什么说“快速”&#xff0c;重要的一点是&#xff0c;很多工具是现成的&#xff0c;可以拿来直接就用。比如数据导出&#xff0c;如果需要把数据集导出为excel格式文件&#xff0c;写代码可能需要很多时间。lazarus就不用了&#xff0c…

多测师肖sir_高级金牌讲师_jenkins搭建

jenkins操作手册 一、jenkins介绍 1、持续集成&#xff08;CI&#xff09; Continuous integration 持续集成 团队开发成员每天都有集成他们的工作&#xff0c;通过每个成员每天至少集成一次&#xff0c;也就意味着一天有可 能多次集成。在工作中我们引入持续集成&#xff0c;通…

apachesolr中简单使用

core使用 首先点击add core 可以看到报错solrconfig.xml不在new_core目录下&#xff0c;new_core是我们点击后自动创建的 那么我们将D:\solr2\solr-9.3.0\solr-9.3.0\server\solr\configsets下的任何一个目录下的conf拷贝到new_core过去 这里是使用_default下的conf目录拷贝…

python爬虫(数据获取——selenium)

环境测试 from selenium import webdriverchromedriver_path r"C:\Program Files\Google\Chrome\Application\chromedriver.exe" driver webdriver.Chrome()url "https://www.xinpianchang.com/discover/article?fromnavigator" driver.get(url)drive…

棱镜七彩亮相工控中国大会,以软件供应链安全助力新型工业化高质量发展

2023年11月1日-3日&#xff0c;2023第三届工控中国大会在苏州国际会议中心举办&#xff0c;本届大会由中国电子信息产业发展研究院、中国工业经济联合会、国家智能制造专家委员会、国家产业基础专家委员会、江苏省工业和信息化厅、江苏省国有资产监督管理委员会、苏州市人民政府…

深度学习框架TensorFlow.NET环境搭建1(C#)

测试环境 visual studio 2017 window10 64位 测试步骤如下&#xff1a; 1 新建.net framework控制台项目&#xff0c;工程名称为TensorFlowNetDemo&#xff0c;.net framework的版本选4.7.2&#xff0c;如下图&#xff1a; 2 分别安装TensorFlow.NET包(先装)和SciSharp.…

sql中的加减乘除

自学SQL网(教程 视频 练习全套)

C++二分算法的应用:乘法表中第k小的数

涉及知识点 二分查找 题目 几乎每一个人都用 乘法表。但是你能在乘法表中快速找到第 k 小的数字吗&#xff1f; 乘法表是大小为 m x n 的一个整数矩阵&#xff0c;其中 mat[i][j] i * j&#xff08;下标从 1 开始&#xff09;。 给你三个整数 m、n 和 k&#xff0c;请你在大…

CSS默认宽度

所谓的默认宽度&#xff0c;就是不设置width属性时&#xff0c;元素所呈现出来的宽度 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title></title><style>* {margin: 0;padding: 0;}.box {/…

GPT-4 变笨加剧,一个笑话讲八百遍;ChatGPT 之父剑桥演讲遭抵制丨 RTE 开发者日报 Vol.77

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE &#xff08;Real Time Engagement&#xff09; 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文…

ActiveMq学习⑨__基于zookeeper和LevelDB搭建ActiveMQ集群

引入消息中间件后如何保证其高可用&#xff1f; 基于zookeeper和LevelDB搭建ActiveMQ集群。集群仅提供主备方式的高可用集群功能&#xff0c;避免单点故障。 http://activemq.apache.org/masterslave LevelDB&#xff0c;5.6版本之后推出了LecelDB的持久化引擎&#xff0c;它使…

开源项目管理工具Helper的安装及汉化

什么是 Helper &#xff1f; Helper 是基于 Laravel 和 Filament 的开源项目管理工具。 官方提供了在线演示&#xff1a;https://project-helper.net 安装 在群晖上以 Docker 方式安装。 数据库理论上是可以使用群晖自带的 MariaDB 的&#xff0c;但老苏为了省事&#xff0c…

【C++基础知识学习笔记】精华版(复习专用)

常用语法 函数重载(Overload) 规则: 函数名相同 参数个数不同、参数类型不同、参数顺序不同 注意: 返回值类型与函数重载无关 调用函数时,实参的隐式类型转换可能会产生二义性 默认参数 C++ 允许函数设置默认参数,在调用时可以根据情况省略实参。规则如下: 默认参数只能…

MySQL的event的使用方法

MySQL的event的使用方法 一、事件定时策略 1、查看event事件开启状态 SHOW VARIABLES LIKE event_scheduler;如图&#xff0c;Value值 ON&#xff1a;打开&#xff0c;OFF&#xff1a;关闭。 2、设置event事件打开 SET GLOBAL event_scheduler ON;如果MySQL重启了&#x…

力扣 138. 随机链表的复制

题目描述&#xff1a; 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &#xff0c;该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成&#xff0c;其中每个新节点的值都设为其对应的…

3+单细胞+代谢+WGCNA+机器学习

今天给同学们分享一篇生信文章“Identification of new co-diagnostic genes for sepsis and metabolic syndrome using single-cell data analysis and machine learning algorithms”&#xff0c;这篇文章发表Front Genet.期刊上&#xff0c;影响因子为3.7。 结果解读&#x…

pytest中的pytest.ini

[pytest] filterwarnings ignore::DeprecationWarning addopts -v -s markers uat:1 smok:2 log_cli1 xfail_strict True filterwarnings ignore::DeprecationWarning 这个的功能就是 test_login.py::Test_login::test_login_correct_password PASSEDwarnings summary …

node教程(四)Mongodb+mongoose

文章目录 一、mongodb1.简介1.1Mongodb是什么&#xff1f;1.2数据库是什么&#xff1f;1.3数据库的作用1.4数据库管理数据的特点 2.核心概念3.下载安装与启动4.命令行交互4.1数据库命令4.3文档命令 二、Mongoose1.介绍2.作用3.使用流程4.插入文档5.mongoose字段类型 三、图形化…

【Unity ShaderGraph】| 快速制作一个 表面水纹叠加效果

前言 【Unity ShaderGraph】| 快速制作一个 表面水纹叠加效果一、效果展示二、表面水纹叠加效果三、应用实例 前言 本文将使用ShaderGraph制作一个表面水纹叠加效果&#xff0c;可以直接拿到项目中使用。对ShaderGraph还不了解的小伙伴可以参考这篇文章&#xff1a;【Unity Sh…