垃圾收集器:利用垃圾收集算法,实现垃圾回收的实践落地。

1 HotSpot垃圾回收器

HotSpot垃圾回收器有多个,可以配合使用。

1.1 垃圾回收的一些术语

术语: Stop the world

简写为STW,也叫全局停顿,Java代码停止运行,native代码继续运行,但不能与JVM进行交互。

STW主要是为了GC操作的准确性和效率。用户线程不停止的话,会不断有新对象和垃圾对象产生,假设没有STW,会导致GC时间过长,错误清理新对象等情况。

原因:多半由于垃圾回收导致;也可能是Dump线程、死锁检查、Dump堆等导致

危害:服务停止、没有响应主从切换(对于高可用环境,如果停顿时间过长,会引发主从之间的切换)、危害生产安全。

因此,尽量缩短Stop the world的时间

术语--并行收集 VS 并发收集

并行收集:指多个垃圾收集线程并行工作,但是在收集的过程中,用户线程(你的业务线程)还是处于等待状态的

并发收集:指用户线程与垃圾收集线程同时工作

术语-- 吞吐量

CPU用于运行用户代码的时间与CPU总消耗时间的比值

公式:运行用户代码时间/(运行用户代码时间+垃圾收集时间)

2 新生代垃圾收集器(与老年代收集器配合使用)

2.1 Serial收集器

Serial 收集器是最基本、发展历史最悠久的收集器,采用复制算法。采用单线程操作,收集过程中全程STW

适用场景有:

  • 客户端程序,应用以-client 模式运行时,默认使用的就是Serial(java -client -jar 运行)
  • 单核机器

2.2 ParNew收集器

Serial收集器的多线程版,除使用多线程以外,其他和Serial收集器一样,包括:JVM参数、Stop the world表现、垃圾收集算法都是一样的。可使用 -XX:ParallelGCThreads设置垃圾收集的线程数。主要和CMS垃圾收集器配合使用。

2.3 ParallelScavenge收集器

ParallelScavenge收集器,是吞吐量优先收集器,也是采用复制算法,也是多线程的。执行过程与ParNew收集器类似。

Parallel Scavenge收集器适用于注重吞吐量的场景。

Parallel Scavenge收集器特点

可以达到一个可控制的吞吐量

  • -XX:MaxGCPauseMillis:控制最大的垃圾收集停顿时间(尽力)

  • -XX:GCTimeRatio:设置吞吐量的大小,取值0-100,系统花费不超过1/(1+n)的时间用于垃圾收集

自适应GC策略:可用-XX:+UseAdptiveSizePolicy打开

  • 打开自适应策略后,无需手动设置新生代的大小(-Xmn)、Eden与Survivor区的比例(-XX:SurvivorRatio)等参数虚拟机会自动根据系统的运行状况收集性能监控信息,动态地调整这些参数,从而达到最优的停顿时间以及最高的吞吐量。

3 老年代收集器(与新生代收集器配合使用)

3.1 Serial Old收集器

Serial Old收集器是Serial收集器的老年代版本,单线程,采用的是标记-整理算法,垃圾收集过程Stop The World。

可以与上面三个新生代收集器配合使用;当CMS收集器出现故障时,作为后备处理器。

3.2 Parallel Old收集器

Parallel Old收集器是Parallel Scavenge收集器的老年代版本,只能与Parallel Scavenge收集器配合使用,同样是注重对吞吐量要求较高的场景。

Parallel Old收集器,采用多线程,标记-整理算法,垃圾收集过程Stop The World。

3.3 CMS收集器(JDK9废弃)

CMS: Concuerrent mark sweep(并发标记收集器),采用标记-清除算法。

CMS执行过程的七个阶段:

  1. 初始标记:标记GC Roots能直接关联的对象,触发短暂STW操作
  2. 并发标记:找出所有GC Roots能关联的对象。并发执行,不会触发STW。
  3. 并发预清理阶段(可选):重新标记在并发标记阶段引用被更新的对象,从而减少后面重新标记的工作量。并发执行,不会触发STW。可使用-XX:-CMSPrecleaningEnabled关闭并发预清理阶段,默认打开。
  4. 并发可中止的预清理阶段(可选):和并发预清理做的事情一样,并发执行,无 Stop The World。预清理后,当Eden的使用量大于CMSScheduleEdenSizeThreshold的阈值(默认2M)时,才会执行该阶段。主要作用是允许我们能够控制预清理阶段的结束时机。
  5. 重新标记阶段:修正并发标记期间,因为用户程序继续运行,导致标记发生变动的那些对象的标记。一般来说,重新标记花费的时间会比初始标记阶段长一些,但比并发标记的时间短。存在 Stop The World。
  6. 并发清除阶段:基于标记结果,清除垃圾对象。并发执行,无STW。使用标记清除算法,因为标记整理涉及数据位置,并发情况难以实现。
  7. 并发重置阶段:清除本地CMS GC的上下文信息,为下次GC做准备。

CMS收集器的优缺

优点:STW时间较短,大多数过程并发执行。

缺点:

  1. 垃圾回收并发执行时,会与用户线程有一定CPU资源争抢,影响吞吐量;
  2. CMS只在标记的时候STW,清除时无STW,无法处理浮动垃圾;
  3. 采用标记-清除法,导致内存碎片的产生;
    1. 可以使用UseCMSCompactAtFullCollection:在完成Full GC后是否要进行内存碎片整理,默认开启。CMSFullGCsBeforeCompaction:进行几次Full GC后就进行一次内存碎片整理,默认是0。
  4. 无法等到老年代几乎满了才开始垃圾收集。
    1. 执行过程中多个阶段没有STW操作,会不断有对象晋升到老年代,当老年代预留的内存不够时,会导致Concurrent Mode Failure,从而切换成后备老年代收集器 Serial Old。
    2. 可使用 CMSInitiatingOccupancyFraction设置老年代占比达到多少就触发垃圾收集,默认68%。

CMS适用于希望系统停顿时间短,响应速度快的场景,例如Web。

扩展:并发预处理、并发中断预处理

1、首先,CMS是一个关注停顿时间,以回收停顿时间最短为目标的垃圾回收器。并发预处理阶段做的工作是标记,重标记需要STW(Stop The World),因此重标记的工作尽可能多的在并发阶段完成来减少STW的时间。此阶段标记从新生代晋升的对象、新分配到老年代的对象以及在并发阶段被修改了的对象。

2、并发可中断预清理(Concurrent precleaning)是标记在并发标记阶段引用发生变化的对象,如果发现对象的引用发生变化,则JVM会标记堆的这个区域为Dirty Card。那些能够从Dirty Card到达的对象也被标记(标记为存活),当标记做完后,这个Dirty Card区域就会消失。CMS有两个参数:CMSScheduleRemarkEdenSizeThreshold、CMSScheduleRemarkEdenPenetration,默认值分别是2M、50%。两个参数组合起来的意思是预清理后,eden空间使用超过2M时启动可中断的并发预清理(CMS-concurrent-abortable-preclean),直到eden空间使用率达到50%时中断,进入重新标记阶段。

4 G1收集器

G1(Garbge First),面向服务端应用,可以同时用于新生代和老年代。

G1收集器使用Region作为单位,包括四种类型,分别为Eden、Survior、Old和Humongous,通过参数-XX:G1HeapRegionSize指定Region的大小,取值范围为1MB ~ 32 MB之间。

前三种Region仍然是伊甸园、存活区、老年代,Humongous用来存储大对象,对象过大可以存储到连续的Humongous中。Old和Humongous同属于老年代。

G1收集器的设计思想将内存分成很多小块(Region),跟踪每个Region中垃圾堆积的价值大小,构建一个优先列表,根据允许的收集时间,优先回收价值最高的Region。其中价值大小指的是回收该Region能获得的空间大小以及回收所需要的时间成本。

4.1 G1收集器的垃圾回收机制

主要分为三种,Young GC、Mixed GC、Full GC。

4.1.1 Young GC

所有Eden Region都满了的时候,就会触发Young GC。

  • Eden中存活的对象转移到Survior Region;
  • 原先 Survivor Region中的对象转移到新的 Survivor Region中,或者晋升到Old Region。
  • 空闲 Region会被放入空闲列表中,等待下次被使用。

4.1.2 Mixed GC

老年代大小占整个堆的百分比达到一定阈值(可用-XX:InitiatingHeapOccupancyPercent指定,默认45%),就触发Mixed GC,会回收所有 Young Region,同时回收部分 Old Region。

执行过程分为四步:

  1. 初始标记:跟CMS类似,标记处GC Roots能直接关联到的对象,存在短暂STW

  2. 并发标记:跟CMS类似,找出所有GC Roots能关联的对象。并发执行,不会触发STW。

  3. 最终标记:更新在并发标记期间引起的变更,存在STW

  4. 筛选回收:首先对各个Region的回收价值和成本排序,根据用户所期望的停顿时间指定回收计划,筛选出合适的Region回收。停顿时间:MaxGCPauseMillis。

    回收过程:将Region的存活对象复制到空闲Region中,然后删除原Region,是复制算法,无内存碎片,过程存在STW。

G1收集器Mixed GC除了并发标记以外的过程都是STW的,由于一次只回收一部分Region,所以停顿时间可控。

4.1.3 Full GC

复制对象内存不够,或者无法分配足够的内存(例如大对象无法分配连续的内存),就会触发Full GC。Full GC机制采用单线程的Serial Old模式。

因此G1收集器的优化原则是,尽可能的减少Full GC。

4.2 G1优化原则:减少Full GC

  1. 增加预留内存(增大-XX:G1 Reserve Percent,默认为堆的10%)
  2. 更早地回收垃圾(减少- XX: InitiatingHeapOccupancyPercent,老年代达到该值就触发 Mixed GC,默认45%
  3. 增加并发阶段使用的线程数(增大-XX: ConcGCThreads)

上面三点大白话总结:多留一点内存,有内存可以分配;有垃圾早点回收;垃圾回收快点。

4.3 G1收集器的使用

G1收集器作用于整个堆,可以控制停顿时间(MaxGCPauseMillis=200),并且没有内存碎片。

G1收集器占用内存较大(通常需要6G以上),可以代替CMS收集器。对于JDK8,主要根据内存选择,内存小于6G,选CMS;内存大于6G,使用G1。CMS在JDK9中被废弃,高于JDK8的版本可以选G1。

5 实验收集器

截止目前JDK14依然处于实验状态

  • Shenandoah(IBM开发,是ZGC竞品,进入OpenJDK,被Oracle JDK12剔除。)

  • ZGC(一款革命性的收集器)

  • Epsilon:不干活的垃圾收集器。

    • 控制内存分配,但是不执行垃圾回收工作,堆耗尽就直接关闭JVM。

6 如何选择垃圾收集器?

理论出发主要有下面几点。

  1. 项目主要关注矛盾点。例如吞吐量(Parallel)、访问延迟(CMS/G1)、应用启动速度
  2. 基础设施:CPU、内存等
  3. JDK版本。例如JDK6没有G1,Oracle JDK没有Shenandoah。

JVM垃圾收集器专题的更多相关文章

  1. JVM调优:HotSpot JVM垃圾收集器

    HotSpot JVM垃圾收集器 - Snooper - 博客园https://www.cnblogs.com/snooper/p/8718478.html

  2. JVM垃圾收集器-Parallel Scavenge收集器

    今天我给大家讲讲JVM垃圾收集器-Parallel Scavenge收集器 Parallel Scavenge收集器 Parallel Scavenge收集器也是一个新生代收集器,它也是使用复制算法的 ...

  3. 7种JVM垃圾收集器特点,优劣势、及使用场景

    今天继续JVM的垃圾回收器详解,如果说垃圾收集算法是JVM内存回收的方法论,那么垃圾收集器就是内存回收的具体实现. 一.常见的垃圾收集器有3类 1.新生代的收集器包括 Serial PraNew Pa ...

  4. 【006】【JVM——垃圾收集器总结】

     Java虚拟机学习总结文件夹 JVM--垃圾收集器总结 垃圾收集器概览 收集算法是内存回收的方法论.垃圾收集据是内存回收的详细实现.Java虚拟机规范中对垃圾收集器应该怎样实现没有规定.不同的厂 ...

  5. 第五章 JVM垃圾收集器(1)

    说明:垃圾回收算法是理论,垃圾收集器是回收算法的实现,关于回收算法,见<第四章 JVM垃圾回收算法> 1.七种垃圾收集器 Serial(串行GC)-- 复制 ParNew(并行GC)-- ...

  6. 第六章 JVM垃圾收集器(2)

    上一章记录了几种常见的垃圾收集器,见<第五章 JVM垃圾收集器(1)> 1.G1 说明: 从上图来看,G1与CMS相比,仅在最后的"筛选回收"部分不同(CMS是并发清除 ...

  7. JVM垃圾收集器(1)

    此文已由作者赵计刚薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 说明:垃圾回收算法是理论,垃圾收集器是回收算法的实现,关于回收算法,见<第四章 JVM垃圾回收算法& ...

  8. 5种JVM垃圾收集器特点和8种JVM内存溢出原因

    先来看看5种JVM垃圾收集器特点 一.常见垃圾收集器 现在常见的垃圾收集器有如下几种: 新生代收集器: Serial ParNew Parallel Scavenge 老年代收集器: Serial O ...

  9. 7种 JVM 垃圾收集器特点、优劣势及使用场景(多图)

    7种 JVM 垃圾收集器特点.优劣势及使用场景(多图)  mp.weixin.qq.com 点击上方"IT牧场",选择"设为星标"技术干货每日送达! 一.常见垃 ...

随机推荐

  1. [web安全] 利用pearcmd.php从LFI到getshell

    有一段时间没写blog了,主要是事多,加上学的有些迷茫,所以内耗比较大.害,沉下心好好学吧. 漏洞利用背景: 允许文件包含,但session等各种文件包含都已经被过滤了.ctf题中可以关注regist ...

  2. 解决springboot序列化 json数据到前端中文乱码问题

    前言 关于springboot乱码的问题,之前有文章已经介绍过了,这一篇算是作为补充,重点解决对象在序列化过程中出现的中文乱码的问题,以及后台报500的错误. 问题描述 spring Boot 中文返 ...

  3. html块 布局

    可通过<div>和<span>将html元素组合起来. Html块元素 大多数html元素被定义为块级元素或内联元素. 块级元素在浏览器显示时,通常会以新行来开始(和结束).例 ...

  4. Linux运维实战之磁盘分区、格式化及挂载(一)

    在网络系统中,磁盘和文件系统管理是两个非常基本.同时也是非常重要的管理任务,特别是文件系统管理,因为它与用户权限和整个网络系统的安全息息相关.本次博文的主题是关于Linux系统中磁盘分区.格式化及挂载 ...

  5. Linux 网卡配置文件,命令详细设置

    1.配置文件/etc/hosts(本地主机ip地址映射,可以有多个别名)./etc/services(端口号与标准服务之间的对应关系)./etc/sysconfig/network(设置主机名,网关, ...

  6. Zookeeper的选举算法和脑裂问题

    ZK介绍 ZK = zookeeper ZK是微服务解决方案中拥有服务注册发现最为核心的环境,是微服务的基石.作为服务注册发现模块,并不是只有ZK一种产品,目前得到行业认可的还有:Eureka.Con ...

  7. MFC入门示例之水平滚动条和垂直滚动条(CScroll Bar)

    初始化滚动条 1 //初始化滚动条 2 SCROLLINFO si = { 0 }; 3 si.cbSize = sizeof(si); 4 si.fMask = SIF_RANGE | SIF_PA ...

  8. 4、BFS算法套路框架——Go语言版

    前情提示:Go语言学习者.本文参考https://labuladong.gitee.io/algo,代码自己参考抒写,若有不妥之处,感谢指正 关于golang算法文章,为了便于下载和整理,都已开源放在 ...

  9. MH/T4029.3 IFPL报文解析

    MH/T4029.3是民航业用来规定飞行计划相关数据交互的规范,今天我们先来解析下其中I类的IFPL报文. 我们先来看看IFPL报文长啥样. ZCZC -TITLE IFPL -FILTIM 0109 ...

  10. JavaScript 判断变量是否为空---三元运算,元组获取值-重组.map()。

    var from_days = getQueryString('from_days'); undefined {'from_days': (from_days) ? from_days : null} ...