jvm之垃圾收集二之常用垃圾收集器
前面简单介绍了如何确定对象是垃圾、什么时候回收、怎么回收,今天就来聊一聊java中常见的垃圾回收器,从Serial到G1,其中会着重解读CMS和G1的工作原理,包括如何安全的并发回收、cSet、rSet等以及他们各自的优缺点;下面按照新生代、老年代进行分类介绍
新生代垃圾回收器
一、Serial收集器(STW)
Serial收集器是一个单线程的、采用标记-复制算法的、回收时需要暂停用户线程(STW)的新生代垃圾回收器;可与serial old或cms搭配使用;但JDK9后已不再支持Serial与CMS的组合
二、ParNew收集器(STW)
ParNew是Serial的多线程版,即垃圾回收线程有多个,但是也是需要STW,回收算法采用的也是标记-复制,除了Serial收集器外只有它可与CMS搭配工作;但自JDK9后已不再支持其与SerialOld的组合,加上上文说的也不支持Serial与CMS的组合,所以JDK9后能与CMS搭配的新生代回收器只有ParNew了;
三、Parallel Scavenge(STW)
与ParNew一致,Parallel Scavenge是基于标记-复制算法的多线程的新生代垃圾回收器,但是其关注的是吞吐量优先;吞吐量高意味着垃圾收集的时间短,而要确保垃圾收集时间短,在回收策略优化调整的基础上也会不可避免的会使垃圾回收的次数增加,而垃圾回收次数增加又会造成用户代码的停顿次数变多,这就要看用户根据实际情况取舍了,一般针对cpu密集型的程序更关注吞吐量,而io密集型的就需要去平衡下吞吐量和用户代码停顿时间的关系了;
- 吞吐量
吞吐量=执行用户线程的时间/(执行用户线程的时间+垃圾收集的时间) - Parallel Scavenge的常用参数
-XX:MaxGCPauseMills;指定垃圾收集能停顿的最大时间,单位毫秒,收集器将尽量保证垃圾回收的时间不超过该设定的时间;
-XX:GCTimeRatio;设置吞吐量大小,取值范围为0-100
-XX:+UseAdaptiveSizePolicy;开关参数;开启后就不用用户去指定新生代的大小(-Xmn)、Eden与Survivor的比例(-XX:SurvivorRatio)等参数了,虚拟机会根据当前系统的运行情况自动收集性能监控信息,动态调整这些参数以达到最合适的停顿时间或吞吐量,这种调节方式称为垃圾收集的自适应调节;
老年代垃圾回收器
一、Serial Old(STW)
是Serial收集器的老年代版本,负责回收老年代,同意也是单线程GC,由于回收的是老年代,没有其他的空积做担保,所以采用的是标记-整理算法
二、Parallel Old(STW)
多线程的基于标记-整理算法的老年代垃圾回收器;是Parallel Scavenge的老年代版本;PS+PO的搭配也是JDK8的默认垃圾收集器的搭配;
三、CMS
是一款关注用户响应时间的老年代垃圾回收器,其在回收中的某些阶段做到了不用暂停用户线程,这在垃圾收集器的历史上具有里程碑的意义,但是其在触发FULLGC后清理老年代的回收器是Serial,单线程的垃圾回收器,显而易见的慢;另外CMS还是唯一一款会单独回收老年代(Old GC)的垃圾回收器,下面介绍下CMS的回收过程以及优缺点
- 回收过程
1、初始标记(STW)
只标记gcroots可直接关联的对象,时间会很快;
2、并发标记
标记那些需要被回收的对象,是与用户线程一起运行的,所以有可能会产生漏标的情况发生,CMS使用的是三色标记算法的增量更新算法来解决这一问题,算法详情可参考上篇文章;
3、重新标记(STW)
针对并发标记阶段用户线程产生的新垃圾进行重新标记
4、并发回收
开始回收垃圾,因为同样是与用户线程一起运行的,所以用户线程会产生新的垃圾,这些垃圾被称为浮动垃圾,只能下次清理时处理; - 优点
支持垃圾线程和用户线程并发执行,减少了用户的等待时间 - 缺点
结合回收过程CMS的缺点也是显而易见的,大致可分为以下三种:
1、由于最后回收阶段采用的是并发回收,用户线程产生的垃圾是必须要到下次GC才会被回收,会产生浮动垃圾;
2、并发回收阶段采用的是标记-清除算法,这样容易产生内存碎片,导致内存不规整,有可能分配不下大对象而产生FULLGC,而上面也说过了,FULLGC时CMS采用的是Serial
3、CMS并发回收阶段使用的线程数是通过(CPU核心数+3)/4计算而来,这样一来,CPU核数大于4还好,如果小于4的话那就意味着最差需要用一半的线程来进行垃圾回收,回影响系统的吞吐量
全堆垃圾收集器
G1
G1是一款面向全推进行回收的可以与用户线程一起进行的垃圾回收器;其在CMS的基础上做了一定程度的优化,但成本就是堆内需要使用部分内存来供G1本身使用;与上面介绍的一堆垃圾收集器相比,G1只在逻辑上进行了分代,物理上比没有划定哪些区域是新生代或老年代;G1还推出了时间响应模型即在给定的M毫秒时间内用于垃圾回收的时间不超过N毫秒,这一实现主要依赖于collection set(CSet)来实现;下面介绍下G1的回收模型和优缺点
回收模型
minorGC
新生代的初始大小有个默认值,约占堆空间的5%-60%,由G1根据需要动态调整;当达到设置的阈值时进行YGC
MixedGC
- 定义
G1与上面介绍的其他收集器不同,不用将新老年代限制死,回收时要么回收新生代(minorGC),要么老年代(majorGC)要么全堆收集(FullGC),G1可以面向堆内存的任何部分来组成回收集(Cset)进行回收;衡量标准不再是垃圾属于哪个分代,而是哪块内存垃圾多回收收益最大,这就是G1的MixGc模式;MixedGC也会有个触发的默认值.超过该值进行GC,默认应该是堆空间的45% - 回收过程
1、初始标记:和CMS的初始标记一样只标记GC Roots能直接关联到的对象,并修改TAMS指针的值,让下一阶段用户线程并发运行时能正确地在可用的region中分配对象;需要暂停用户线程,但耗时很短,且是借用Minor GC的时候同步完成的,所以并没有额外的停顿
2、并发标记:从GC Root开始对堆中对象进行可达性分析,找出要回收的对象,耗时较长所以可以与用户线程并发执行;扫描完后会维护SATB记录下来的并发时由用户线程造成的引用发生改变的对象(三色标记的SATB算法)
3、最终标记:暂停用户线程,处理并发标记阶段SATB中维护的引用发生改变的记录
4、筛选回收:暂停用户线程,对各region的回收价值和回收成本进行排序,根据用户期望的停顿时间来制定回收计划,可以选择任意个region构成回收集,然后把需要回收的region中的存货对象复制到空的region中,再清理掉region的全部空间;由多条GC线程并行完成上述操作
FullGC
当堆空间不足以分配新对象时触发FGC
优点
1、全堆垃圾收集器;
2、仅进行了逻辑上的分代,物理上并不分代;
3、逻辑上保留了新老年代的概念,但新老年代的位置并不固定,它们是一系列区域(不需要连续)的动态集合;
4、Region为G1的最小回收单元;可由-XX:G1HeapRegionSize设定每个region的大小,取值范围为1-32MB,且应为2的N次幂
5、利用停顿时间模型用户可以指定垃圾收集的停顿时间,G1也会尽量满足这个设定的时间
缺点
1、为了垃圾收集而产生的内存占用和程序运行时的额外执行负载都比CMS要高
2、G1每个region中维护的记忆集(Rset)可能会占整个堆容量的20%甚至更多;而CMS使用的是卡表,全堆只需维护一份,且只需记录老年代到新生代的引用;
collections set(cSet)
维护了需要下次垃圾回收的region的集合,并且根据回收价值进行了排序,这样筛选回收时就能根据系统默认或者用户设定的响应时间优先回收价值高的region
remember set(rSet)
每个region维护一个rSet,用来记录别的对象到本region的引用,用rSet就是为了解决垃圾回收时对象跨代引用的扫描问题,这样操作大大节省了GC回收时扫描的时间;但是随之而来的问题是,维护rSet也是需要一定内存空间的;
jvm之垃圾收集二之常用垃圾收集器的更多相关文章
- JVM系列(二) — Java垃圾收集介绍
这篇文章主要从以下几个方面介绍垃圾收集的相关知识 一.判断对象是否已死 二.主流垃圾收集算法 三.内存分配与回收策略 本章节主要从以下几个思考点着手介绍垃圾回收的相关知识:哪些内存需要回收?什么时候回 ...
- JVM知识(二):类加载器原理
我们知道我们编写的java代码,会经过编译器编译成字节码(class文件),再把字节码文件装载到JVM中,最后映射到各个内存区域中,我们的程序就可以在内存中运行了.那么问题来了,这些字节码文件是怎么装 ...
- JVM(HotSpot)7种垃圾收集器
JVM(HotSpot)7种垃圾收集器 7种垃圾收集器作用于不同的分代,如果两个收集器之间存在连续,就说明他们可以搭配使用. 从JDK1.3到现在,从Serial收集器->Parallel收集器 ...
- 【Java】JVM(三)、Java垃圾收集器
一.Minor GC.Major GC 和 Full GC Minor GC:清理新生代空间,当Eden空间不能分配时候引发Minor GC Major GC:清理老年代空间 Full GC:清理Ja ...
- JVM学习笔记-第三章-垃圾收集器与内存分配策略
JVM学习笔记-第三章-垃圾收集器与内存分配策略 tips:对于3.4之前的章节可见博客:https://blog.csdn.net/sanhewuyang/article/details/95380 ...
- 垃圾收集器之:G1收集器
G1垃圾收集器是一种工作在堆内不同分区上的并发收集器.分区既可以归属于老年代,也可以归属新生代,同一个代的分区不需要保持连续.为老年代设计分区的初衷是我们发现并发后台线程在回收老年代中没有引用的对象时 ...
- [转帖]JVM—深入理解内存模型与垃圾收集机制
JVM—深入理解内存模型与垃圾收集机制 https://juejin.im/post/5d68dc9ee51d4561ad6548f7 前言 Java是一种跨平台的语言,当初其设计初衷也是为了解决各个 ...
- 垃圾收集器之:CMS收集器
HotSpot JVM的并发标记清理收集器(CMS收集器)的主要目标就是:低应用停顿时间.该目标对于大多数交互式应用很重要,比如web应用.在我们看一下有关JVM的参数之前,让我们简要回顾CMS收集器 ...
- JVM体系结构之二:类加载器
一.概述 定义:虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型.类加载和连接的过程都是在运行期间完成的. 二. 类的加载 ...
随机推荐
- Python自学教程7:字典类型有什么用
字典是Python中的一个重要操作,如果字典玩得顺,很多其他的数据类型就可以一通百通. Python字典的定义 字典使用一对大括号进行定义,键值对之间使用逗号隔开,键和值使用冒号分隔. 键必须是不可变 ...
- 【LOJ#3197】【eJOI2019】T形覆盖 - (图论、简单推导)
题面 题解 (题目中说的四种摆放方式实际上是分别旋转0°,90°,180°,270°后的图形) 题目中关于摆放方式的描述听起来很臭,我们把它转换一下,每个拼版先覆盖"上下左右中"五 ...
- KingbaseES行转列(PIVOT)
如果以交叉表格式显示,则商业智能查询返回的数据通常是最有用的.SELECT语句的pivot_.数据透视是数据仓库中的一项关键技术.在其中,您可以将多行输入转换为数据仓库中较少且通常较宽的行.进行数据透 ...
- Springboot_maven多环境配置
开发过程中总是需要多环境配置,而Spring自带的方式不是那么优秀,可以利用maven来帮助做到 可以再pom.xml中配置profiles来做到 打包命令: mvn clean package -P ...
- Springboot log4j2总结
Log4j2 PS: Log4j 已不再维护,而最新的是Log4j2, Log4j2 是全部重写了Log4j,并拥有更加优秀的性能 1. 引入依赖,和去掉logging的依赖 <dependen ...
- Linux云主机安全入侵排查步骤
导语 经常有用户报障系统被植入恶意程序,如挖矿软件.ddos攻击病毒.syn映射攻击病毒等,可以按照以下流程为用户排查入侵病毒类型: 一.定位病毒进程 对于用户反馈云主机性能卡顿,CPU和内存占用较高 ...
- 2020年12月-第01阶段-前端基础-HTML CSS 项目阶段(二)
品优购项目(二) 1. 品优购首页布局 命名集合: 名称 说明 快捷导航栏 shortcut 头部 header 标志 logo 购物车 shopcar 搜索 search 热点词 hotwrods ...
- 使用 APM 中的 Service Map 了解和调试应用程序
文章转载自:https://blog.csdn.net/UbuntuTouch/article/details/118667839
- tcp_tw_recycle参数引发的系统问题
文章转载自: https://blog.csdn.net/zhuyiquan/article/details/68925707
- Prometheus与服务发现
这种按需的资源使用方式对于监控系统而言就意味着没有了一个固定的监控目标,所有的监控对象(基础设施.应用.服务)都在动态的变化.对于Prometheus这一类基于Pull模式的监控系统,显然也无法继续使 ...