前面简单介绍了如何确定对象是垃圾、什么时候回收、怎么回收,今天就来聊一聊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之垃圾收集二之常用垃圾收集器的更多相关文章

  1. JVM系列(二) — Java垃圾收集介绍

    这篇文章主要从以下几个方面介绍垃圾收集的相关知识 一.判断对象是否已死 二.主流垃圾收集算法 三.内存分配与回收策略 本章节主要从以下几个思考点着手介绍垃圾回收的相关知识:哪些内存需要回收?什么时候回 ...

  2. JVM知识(二):类加载器原理

    我们知道我们编写的java代码,会经过编译器编译成字节码(class文件),再把字节码文件装载到JVM中,最后映射到各个内存区域中,我们的程序就可以在内存中运行了.那么问题来了,这些字节码文件是怎么装 ...

  3. JVM(HotSpot)7种垃圾收集器

    JVM(HotSpot)7种垃圾收集器 7种垃圾收集器作用于不同的分代,如果两个收集器之间存在连续,就说明他们可以搭配使用. 从JDK1.3到现在,从Serial收集器->Parallel收集器 ...

  4. 【Java】JVM(三)、Java垃圾收集器

    一.Minor GC.Major GC 和 Full GC Minor GC:清理新生代空间,当Eden空间不能分配时候引发Minor GC Major GC:清理老年代空间 Full GC:清理Ja ...

  5. JVM学习笔记-第三章-垃圾收集器与内存分配策略

    JVM学习笔记-第三章-垃圾收集器与内存分配策略 tips:对于3.4之前的章节可见博客:https://blog.csdn.net/sanhewuyang/article/details/95380 ...

  6. 垃圾收集器之:G1收集器

    G1垃圾收集器是一种工作在堆内不同分区上的并发收集器.分区既可以归属于老年代,也可以归属新生代,同一个代的分区不需要保持连续.为老年代设计分区的初衷是我们发现并发后台线程在回收老年代中没有引用的对象时 ...

  7. [转帖]JVM—深入理解内存模型与垃圾收集机制

    JVM—深入理解内存模型与垃圾收集机制 https://juejin.im/post/5d68dc9ee51d4561ad6548f7 前言 Java是一种跨平台的语言,当初其设计初衷也是为了解决各个 ...

  8. 垃圾收集器之:CMS收集器

    HotSpot JVM的并发标记清理收集器(CMS收集器)的主要目标就是:低应用停顿时间.该目标对于大多数交互式应用很重要,比如web应用.在我们看一下有关JVM的参数之前,让我们简要回顾CMS收集器 ...

  9. JVM体系结构之二:类加载器

    一.概述 定义:虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型.类加载和连接的过程都是在运行期间完成的. 二. 类的加载 ...

随机推荐

  1. 01 - 快速体验 Spring Security 5.7.2 | 权限管理基础

    在前面SpringBoot 2.7.2 的系列文章中,已经创建了几个 computer 相关的接口,这些接口直接通过 Spring Doc 或 POSTMAN 就可以访问.例如: GET http:/ ...

  2. 第七十七篇:ref引用(在vue中引用组件实例)

    好家伙, 为方便理解, 我们先来写一个经典自增一按钮, 再加上一个count清零按钮, Left.vue组件中: <template> <div > <h1>我是L ...

  3. 【面试题】JS改变this指向的三种方法

    一.this指向 点击打开视频讲解更加详细 this随处可见,一般谁调用,this就指向谁.this在不同环境下,不同作用下,表现的也不同. 以下几种情况,this都是指向window 1.全局作用下 ...

  4. 【疑难杂症】关于Transformer到底是什么

    在学习transform的时候,很多视频上来就是一张图开始解释图里面残差网络,self-attention等等巴拉巴拉的意思,然后组装,看也看完了,但是还是不明白transformer和selfatt ...

  5. Redis基本数据结构ZipList

    为什么要有ziplist 有两点原因: 普通的双向链表,会有两个指针,在存储数据很小的情况下,我们存储的实际数据的大小可能还没有指针占用的内存大,是不是有点得不偿失?而且Redis是基于内存的,而且是 ...

  6. docker 生成mysql镜像启动时自动执行sql

    文章转载自:https://www.jianshu.com/p/12fc253fa37d 在docker 创建 mysql 容器时,往往需要在创建容器的过程中创建database 实例,代码如下: # ...

  7. kibana知识点

    1.Kibana 有 Linux.Darwin 和 Windows 版本的安装包.由于 Kibana 基于 Node.js 运行,我们在这些平台上包含了一些必要的 Node.js 二进制文件.Kiba ...

  8. Elasticsearch实现类Google高级检索

    文章转载自: https://mp.weixin.qq.com/s?__biz=MzI2NDY1MTA3OQ==&mid=2247483914&idx=1&sn=436f814 ...

  9. 使用Filebeat传送多行日志

    文章转载自:https://blog.csdn.net/UbuntuTouch/article/details/106272704 在解决应用程序问题时,多行日志为开发人员提供了宝贵的信息. 堆栈跟踪 ...

  10. CentOS 7.x 升级OpenSSH

    升级SSH 存在中断风险,如果SSH 升级失败将会导致终端无法登录,建议在使用本地虚拟机进行测试后对线上生产环境进行升级操作!!! 三级等保评测中对主机进行漏洞扫描发现linux主机存在高危漏洞,查看 ...