JVM12_评估GC性能指标、垃圾收集器概述、Serial、SerialOld、ParNew、Parallel、ParallelOld

面试遇到面试官问这部分可以这样回答:
不同的厂商会考虑使用不同的JVM,不同的JVM会使用不同的垃圾收集器,下面我介绍下主流的垃圾收集器有哪些(主流的7种),下面你就可以展开去说明七种垃圾收集器的每一个细节。
(1).截止JDK 1.8,一共有7款不同的垃圾收集器。每一款不同的垃圾收集器都有不同的特点,在具体使用的时候,需要根据具体的情况选用不同的垃圾收集器
在这里插入图片描述(2).不同厂商、不同版本的虚拟机实现差别很大。HotSpot 虚拟机在JDK7/8后所有收集器及组合(连线),如下图:
在这里插入图片描述
在这里插入图片描述

①. 评估GC的性能指标

  • ①. 吞吐量:运行用户代码的时间占总运行时间的比例
    吞吐量 = 运行用户代码时间 /(运行用户代码时间 + 垃圾收集时间)
    比如:虚拟机总共运行了100分钟,其中垃圾收集花掉1分钟,那吞吐量就是99%
    吞吐量优先,意味着在单位时间内,STW的时间最短:0.2 + 0.2 = 0.4

在这里插入图片描述

  • ②. 暂停时间:执行垃圾收集时,程序的工作线程被暂停的时间
    暂停时间优先,意味着尽可能让单次STW的时间最短:0.1 + 0.1 + 0.1 + 0.1 + 0.1 = 0.5

在这里插入图片描述

  • ③. 内存占用: Java堆区所占的内存大小

  • ④. 垃圾收集开销:吞吐量的补数,垃圾收集所用时间与总运行时间的比例

  • ⑤. 收集频率:相对于应用程序的执行,收集操作发生的频率
    (类似于大学洗衣服,天天洗,每次很快洗完;一周洗,洗很久)
    (手机频率高,垃圾线程所用时间短,吞吐量低)

  • ⑥. 评估GC的性能指标:吞吐量vs暂停时间

  1. 这三者共同构成一个“不可能三角”。三者总体的表现会随着技术进步而越来越好。一款优秀的收集器通常最多同时满足其中的两项。
  2. 这三项里,暂停时间的重要性日益凸显。因为随着硬件发展,内存占用 多些越来越能容忍,硬件性能的提升也有助于降低收集器运行时对应用程序的影响,即提高了吞吐量。而内存的扩大,对延迟反而带来负面效果。
  3. 简单来说,主要抓住两点:吞吐量、暂停时间
  4. 现在JVM调优标准:在最大吞吐量优先的情况下,降低停顿时间

②. 不同的垃圾回收器概述

  • ①. 垃圾收集器发展史
    1999年随JDK1.3.1一起来的是串行方式的Serial GC ,它是第一款GC。ParNew垃圾收集器是Serial收集器的多线程版本
    2002年2月26日,Parallel GC 和Concurrent Mark Sweep GC跟随JDK1.4.2一起发布
    Parallel GC在JDK6之后成为HotSpot默认GC
    2012年,在JDK1.7u4版本中,G1可用。-XX:+UseG1GC
    2017年,JDK9中G1变成默认的垃圾收集器,以替代CMS
    2018年3月,JDK 10中G1垃圾回收器的并行完整垃圾回收,实现并行性来改善最坏情况下的延迟
    2018年9月,JDK11发布。引入Epsilon 垃圾回收器,又被称为"No-Op(无操作)"回收器。同时,引入ZGC:可伸缩的低延迟垃圾回收器(Experimental)
    2019年3月,JDK12发布。增强G1,自动返回未用堆内存给操作系统。同时,引入Shenandoah GC:低停顿时间的GC(Experimental)
    2019年9月,JDK13发布。增强ZGC,自动返回未用堆内存给操作系统
    2020年3月,JDK14发布。删除CMS垃圾回收器。扩展ZGC在macOS和Windows上的应用

  • ②. 7款经典的垃圾收集器
    串行回收器:Serial、Serial Old
    并行回收器:ParNew、Parallel Scavenge、Parallel Old
    并发回收器:CMS、G1

  • ③. 7款经典的垃圾收集器与垃圾分代之间的关系
    新生代收集器: Serial GC、ParNew GC、Parallel Scavenge GC
    老年代收集器: Serial 0ld GC、 Parallel 0ld GC、 CMS GC
    整堆收集器: G1 GC
    在这里插入图片描述

  • ④. 垃圾收集器的组合关系

  1. 两个收集器间有连线,表明它们可以搭配使用:Serial/Serial 01d、Serial/CMS、 ParNew/Serial 01d、ParNew/CMS、Parallel Scavenge/Serial 01d、Parallel Scavenge/Parallel 0ld、G1;
  2. 其中Serial 0ld作为CMS 出现"Concurrent Mode Failure"失败的后 备预案。
  3. (红色虚线)由于维护和兼容性测试的成本,在JDK 8时将Serial+CMS、ParNew+Serial 01d这两个组合声明为废弃(JEP 173) ,并在JDK 9中完全取消了这些组合的支持(JEP214),即:移除。(绿色虚线)JDK 14中:弃用Parallel Scavenge和Serial0ld GC组合(JEP366 )(青色虚线)JDK 14中:删除CMS垃圾回收器 (JEP 363)

在这里插入图片描述
在这里插入图片描述

  • ⑤. 查看默认的垃圾收集器
  1. -xx:+PrintCommandLineFlags: 查看命令行相关参数(包含使用的垃圾收集器)
/**
 *  -XX:+PrintCommandLineFlags
 *  -XX:+UseSerialGC:表明新生代使用Serial GC ,同时老年代使用Serial Old GC
 *  -XX:+UseParNewGC:标明新生代使用ParNew GC
 *  -XX:+UseParallelGC:表明新生代使用Parallel GC
 *  -XX:+UseParallelOldGC : 表明老年代使用 Parallel Old GC
 *  说明:二者可以相互激活
 *  -XX:+UseConcMarkSweepGC:表明老年代使用CMS GC。同时,年轻代会触发对ParNew 的使用
 */
public class GCUseTest {
    public static void main(String[] args) {
        ArrayList<byte[]> list = new ArrayList<>();

        while(true){
            byte[] arr = new byte[100];
            list.add(arr);
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
输出:
(-XX:InitialHeapSize=268435456 -XX:MaxHeapSize=4294967296 
-XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers 
-XX:+UseCompressedOops -XX:+UseParallelGC)
  1. 使用命令行指令: jinfo 一flag 相关垃圾回收器参数进程ID
    ( jinfo -flag UseParallelGC 进程id
    jinfo -flag UseParallelOldGC 进程id )
    在这里插入图片描述

③. Serial、SerialOld 回收器:串行回收(了解)

  • ①. Serial收集器采用复制算法、串行回收和"Stop一 the一World"机制的方式执行内存回收

  • ②. Serial 0ld收集器同样也采用了串行回收 和"Stop the World"机制,只不过内存回收算法使用的是标记一压缩算法

  • ③. 单线程回收:使用一个cpu或一条线程去完成垃圾收集工作 | 必须暂停其他所有的工作线程

  • ④. 使用 -XX: +UseSerialGC 参数可以指定年轻代和老年代都使用串行收集器
    等价于新生代用Serial GC,且老年代用Serial 0ld GC
    控制台输出:
    -XX:InitialHeapSize=268435456 -XX:MaxHeapSize=4294967296 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseSerialGC
    在这里插入图片描述

④. ParNew回收器:并行回收(了解)

  • ①. 如果说Serial GC是年轻代中的单线程垃圾收集器,那么ParNew收集器则是Serial收集器的多线程版本

  • ②. ParNew收集器除了采用并行回收的方式执行内存回收外,两款垃圾收集器之间几乎没有任何区别。ParNew收集器在年轻代中同样也是采用复制算法、"Stop一 the一World"机制

  • ③. 因为除Serial外,目前只有ParNew GC能与CMS收集器配合工作

  • ④. 在程序中,开发人员可以通过选项"-XX:+UseParNewGC"手动指定使用.ParNew收集器执行内存回收任务。它表示年轻代使用并行收集器, 不影响老年代

  • ⑤. -XX:ParallelGCThreads 限制线程数量,默认开启和CPU数据相同的线程数。
    在这里插入图片描述

  • ⑥. SerialGC 和 ParNewGC哪个更好?

  1. ParNew 收集器运行在多CPU的环境下,由于可以充分利用多CPU、多核心等物理硬件资源优势,可以更快速地完成垃圾收集,提升程序的吞吐量
  2. 但是在单个CPU的环境下,ParNew收集器不比Serial 收集器更高效。虽然Serial收集器是基于串行回收,但是由于CPU不需要频繁地做任务切换,因此可以有效避免多线程交互过程中产生的一些额外开销

⑤. Parallel、ParallelOld:吞吐量优先

  • ①. HotSpot的年轻代中除了拥有ParNew收集器是基于并行回收的以外, Parallel Scav enge收集器同样也采用了复制算法、并行回收和"Stop the World"机制。在Java8中,默认是此垃圾收集器

  • ②. 那么Parallel收集器的出现是否多此一举?

  1. 和ParNew收集器不同,Parallel Scavenge收集器的目标则是达到一个可控制的吞吐量(Throughp ut),它也被称为吞吐量优先的垃圾收集器。
  2. 自适应调节策略也是Parallel Scavenge与ParNew一个重要区别
  • ③. 高吞吐量则可以高效率地利用CPU时间,尽快完成程序的运算任务,主要适合在后台运算而不需要太多交互的任务。因此,常见在服务器环境中使用。例如,那些执行批量处理、订单处理、工资支付、科学计算的应用程序。

  • ④. Parallel收集器在JDK1.6时提供了用于执行老年代垃圾收集的 Parallel 0ld收集器,用来代替老年代的Serial 0ld收集器

  • ⑤. Parallel 0ld收集器采用了标记一压缩算法,但同样也是基于并行回收和”Stop一the一World"机制
    在这里插入图片描述

  • ⑥. 在程序吞吐量优先的应用场景中,Parallel 收集器和Parallel 0ld收集器的组合,在Server模式下的内存回收性能很不错

  • ⑦. 参数配置
    -XX:+UseParallelGC手动指定年轻代使用Parallel并行收集器执行内存回收任务
    -XX:+UseParallelOldGC手动指定老年代都是使用并行回收收集器。
    (分别适用于新生代和老年代。默认jdk8是开启的。上面两个参数,默认开启一个,另一个也会被开启。(互相激活))
    -XX:ParallelGCThreads设置年轻代并行收集器的线程数。一般地,最好与CPU数量相等,以避免过多的线程数影响垃圾收集性能
    (在默认情况下,当CPU 数量小于8个, ParallelGCThreads 的值等于CPU 数量。
    当CPU数量大于8个,ParallelGCThreads 的值等于3+[5*CPU_Count]/8] )

    -XX:MaxGCPauseMillis:设置垃圾收集器最大停顿时间(即STW的时间)。单位是毫秒
    (为了尽可能地把停顿时间控制在MaxGCPauseMills以内,收集器在工作时会调整Java堆大小或者其他一些参数
    对于用户来讲,停顿时间越短体验越好。但是在服务器端,我们注重高并发,整体的吞吐量。所以服务器端适合Parallel,进行控制
    该参数使用需谨慎)
    -XX:+UseAdaptiveSizePolicy 设置Parallel Scavenge收集器具有自适应调节策略
    (在这种模式下,年轻代的大小、Eden和Survivor的比例、晋升老年代的对象年龄等参数会被自动调整,已达到在堆大小、吞吐量和停顿时间之间的平衡点
    在手动调优比较困难的场合,可以直接使用这种自适应的方式,仅指定虚拟机的最大堆、目标的吞吐量(GCTimeRatio)和停顿时间(MaxGCPauseMills),让虚拟机自己完成调优工作)

⑧. 详解-XX:+PrintGCDetails

  • ①. Minor GC
    在这里插入图片描述

  • ②. Full GC
    在这里插入图片描述

  • ③. 举例补充

/**
 * 在jdk7 和 jdk8中分别执行
 * -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+UseSerialGC
 */
public class GCLogTest1 {
    private static final int _1MB = 1024 * 1024;

    public static void testAllocation() {
        byte[] allocation1, allocation2, allocation3, allocation4;
        allocation1 = new byte[2 * _1MB];
        allocation2 = new byte[2 * _1MB];
        allocation3 = new byte[2 * _1MB];
        allocation4 = new byte[4 * _1MB];
    }

    public static void main(String[] agrs) {
        testAllocation();
    }
}

在这里插入图片描述

⑨. 其他垃圾回收器概述

  • ①. Open JDK12的Shenandoah GC
  1. 暂时时间短、吞吐量下降
  2. red hot 团队
  • ②. 革命性的ZGC(jdk11-oracle)
    ( 在尽可能对吞吐量影响不大的前提下.实现在任意堆内存大小都可以把垃圾收集的停顿时间控制在10毫秒之内)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

所得皆惊喜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值