CMS垃圾收集器深入解析

1.CMS的两种模式与一种特殊策略

1.1Backgroud CMS(没有并发失败的情况)

1.1.1并发标记还能被整理成两个流程

(1)初始标记
(2)并发标记(3)(4)在这个阶段发生
(3)并发预处理
(4)可中止的预处理

(5)重新标记
(6)并发清除

1.1.2为什么我们的并发标记细化之后还会额外有两个流程出现呢?

讨论这个问题之前,我们先思考一个问题,假设CMS要进行老年代的垃圾回收,我们如何判断被年轻代的对象引用的老年代对象是可达对象。

当老年代被回收的时候,我们如何判断A对象是存活对象。

必须扫描新生代来确定,所以CMS虽然是老年代的垃圾回收器,却需要扫描新生代的原因。

既然这个时候我需要扫描新生代,那么全量扫描会不会很慢

答:肯定会的 ,但是接踵而来的问题:既然会很慢,我们的停顿时间很长,可是CMS的目标是什么,CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。这不是与他的设计理念不一致吗?

1.1.3那怎么让我们的回收变快?

肯定是垃圾越少越快。所以我们的CMS想到了一种方式,就是我先进行新生代的垃圾回收,也就是一次young GC,回收完毕之后。是不是我们新生代的对象就变少了,那么我再进行垃圾回收,是不是就变快了。可以通过CMS提供的两个参数控制垃圾的回收。

CMSScheduleRemarkEdenSizeThreshold             默认值:2M

CMSScheduleRemarkEdenPenetration              默认值:50%

这两个参数组合起来就是预清理之后,Eden空间使用超过2M的时候启动可中断的并发预清理,(CMS-concurrent-abortable-preclean),到Eden空间使用率到达50%的时候中断(但不是结束),然后进入Remark(重新标记阶段)。

1.1.4这里面有个概念,为什么并发预处理前面会有可中断的意思

可中断意味着,假设你一直在预处理,预处理是干什么,无非就是去帮你把正式应该处理的前置工作给做了。所以他一定干了很多事情,但是这些事情迟早有个头,所以就设置了一个时间对他进行打断。所以,并发预处理的逻辑是当你发生了minor GC  ,我就预处理结束了但是,我怎么知道你什么时候发生minor  GC?

答案是我不知道,垃圾回收是JVM自动调度的,所以我们无法控制垃圾回收,那我不可能无限制的执行下去,总要有个结束时间吧,所以CMS提供了一个参数

CMSMaxAbortablePrecleanTime ,默认为5S

只要到了5S,不管发没发生Minor GC,有没有到CMSScheduleRemardEdenPenetration都会中止此阶段,进入remark,如果在5S内还是没有执行Minor GC怎么办?CMS提供一个参数

CMSScavengeBeforeRemark参数,使remark前强制进行一次Minor GC。

1.2老年代的策略:记忆集解决每次oldGC都要yuongGC的问题

当我们进行young gc时,可作为gc roots的东西除了常见的栈引用、静态变量、常量、锁对象、class对象这些常见的之外,如果老年代有对象引用了我们的新生代对象,那么老年代的对象也应该加入gc roots的范围中,但是如果每次进行young gc我们都需要扫描一次老年代的话,那我们进行垃圾回收的代价实在是太大了,因此我们引入了一种叫做记忆集的抽象数据结构来记录这种引用关系。

记忆集是一种用于记录从非收集区域指向收集区域的指针集合的数据结构。

如果我们不考虑效率和成本问题,我们可以用一个数组存储所有有指针指向新生代的老年代对象。但是如果这样的话我们维护成本就很好,打个比方,假如所有的老年代对象都有指针指向了新生代,那么我们需要维护整个老年代大小的记忆集,毫无疑问这种方法是不可取的。因此我们引入了卡表的数据结构

1.2.1卡表

记忆集是我们针对于跨代引用问题提出的思想,而卡表则是针对于该种思想的具体实现。(可以理解为记忆集是结构,卡表是实现类)

在hotspot虚拟机中,卡表是一个字节数组,数组的每一项对应着内存中的某一块连

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

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

相关文章

Colmap三维重建详解与使用方法

图片捕获过程,请遵循以下指导方针以获得最佳重建结果: 1 捕捉具有良好纹理的图像。避免使用完全没有质感的图片(例如,白色的墙或空桌子)。如果场景本身没有足够的纹理,你可以放置额外的背景对象,如海报等。 2 在相似的照明条件下…

Docker 快速搭建 Gitlab 服务

linux环境: 使用 vim 编辑 hosts 文件: vim /etc/hosts按 I 进入编辑模式,在文件末行追加上虚拟机的 IP 和要设置的域名: 192.168.1.17 gitlab.kunwu.toplwindows环境: Windows 系统的 hosts 文件位于 C:\Windows\S…

如何做一个简单的深度集成学习框架

使用同一个框架,独立在一个数据集上面,分别训练多次,每个单独模型训练超参数可以一样,也可以不一样,最后若干个训练好的独立模型在测试集数据上面做最后集中决策。 实例代码如下: class MyEnsemble(nn.Modu…

linux通过串口传输文件

简介 在嵌入式调试过程中,我们经常会使用调试串口来查看Log或者执行指令,其实,调试串口还有另一种功能,就是传输文件,本文说明使用MobaXterm串口工具来传输文件。 环境要求 嵌入式系统需要安装lsz和lrz,…

【Java】定时器的简单应用

在写代码的过程中,如果我们遇到了隔一段时间就要进行一项任务时,采用定时器会提高我们的效率。下面对定时器的使用进行简单说明 1、应用说明 首先我们要创建一个Timer类 Timer timer new Timer(); 然后在timer中调用schedule()方法添加任务 timer.…

将对象转成URL参数

背景 有的时候前端跳转到其他平台的页面需要携带额外的参数,需要将对象转成用 & 连接的字符串拼接在路径后面。 实现方法

Rust语言入门教程(二) - 变量与作用域

变量与作用域 变量的声明与初始化 Rust的基本语法格式如下: fn main(){let bunnies 2; }语句以分号结尾,用花括号包含语句块。 Rust的语法其实借鉴了很多其他的语言,比如C语言和Python, 所以变量定义的格式看起来也跟很多我们…

Elasticsearch:ES|QL 函数及操作符

如果你对 ES|QL 还不是很熟悉的话,请阅读之前的文章 “Elasticsearch:ES|QL 查询语言简介​​​​​​​”。ES|QL 提供了一整套用于处理数据的函数和运算符。 功能分为以下几类: 目录 ES|QL 聚合函数 AVG COUNT COUNT_DISTINCT 计数为近…

自定义字符-摄氏度汉字一

本文为博主 日月同辉,与我共生,csdn原创首发。希望看完后能对你有所帮助,不足之处请指正!一起交流学习,共同进步! > 发布人:日月同辉,与我共生_单片机-CSDN博客 > 欢迎你为独创博主日月同…

Unity UGUI的HorizontalLayoutGroup(水平布局)组件

Horizontal Layout Group | Unity UI | 1.0.0 1. 什么是HorizontalLayoutGroup组件? HorizontalLayoutGroup是Unity UGUI中的一种布局组件,用于在水平方向上对子物体进行排列和布局。它可以根据一定的规则自动调整子物体的位置和大小,使它…

Python基础:生成器(Generators)和生成器表达式(Generator Expressions)详解

生成器(Generators)和 生成器表达式(Generator Expressions)是 Python 中用于处理迭代器和序列数据的强大工具。它们允许你按需生成值,而不是一次性生成所有值,从而节省内存和提高性能。 1. 生成器&#x…

实现自动化构建与集成:Jenkins与SVN整合的指南

Jenkins整合SVN 前言(非必须):配置Jenkins的CSRF1、新建任务2、 配置SVN3、配置Maven:进行编译打包4.1、发布到WEB容器(第一种:将项目放在webapps下)4.2、发布到WEB容器(第二种:将项目名称修改为…