• JVM垃圾回收器


    1、GC垃圾回收器分类

    • 按线程数量区分:串行垃圾回收器和并行垃圾回收器
      并行垃圾回收器:是通过多个垃圾回收线程并行执行,可使用多个CPU同时执行垃圾回收操作,提升了应用吞吐量,但是和串行回收一样,都会遵循“Stop The World”机制。
      串行垃圾回收器:是单线程执行垃圾回收,且只允许有一个CPU用于垃圾回收操作,此时用户线程会暂停,直至垃圾收集工作结束。串行和并行的区别在于在垃圾回收期间内,用户暂停的时间长短差异。如图:
      image
    • 按工作模式区分:并发式垃圾回收器和独占式垃圾回收器
      并发式垃圾回收器:可以和应用程序线程交互工作,以最大限度减少应用程序的停顿时间。
      独占式垃圾回收器:一旦运行,就会停止应用程序中所有的用户线程,直到垃圾回收完全结束。如图:
      image
    • 按碎片处理方式区分:压缩式垃圾回收器和非压缩式垃圾回收器
      压缩式垃圾回收器会在回收完成以后,对内存中存活对象进行压缩整理,然后消除回收的碎片。
      非压缩式垃圾回收器,不对存活对象进行整理操作。
    • 按工作的内存区间分:年轻代垃圾回收器和老年代垃圾回收器

    2、7款经典垃圾收集器

    • 串行回收器:Serial、Serial Old

    • 并行回收器:ParNew、Parallel Scavenge、Parallel Old

    • 并发回收器:CMS、G1

    • 垃圾回收器在年轻代和老年代中的关系:
      image

    • 垃圾收集器的组合:
      image

    1. 两个收集器之间有连线,说明它们可以搭配使用:
      Serial/Serial Old、Serial/CMS、ParNew/Serial Old、ParNew/CMS、Parallel Scavenge/Serial Old、Parallel Scavenge/Parallel Old、G1
    2. 其中Serial Old是作为CMS出现"Concurrent Mode Failure"失败后的预案。
    3. (红色虚线)由于维护和兼容性测试成本,在JDK 8已经将Serial+CMS、ParNew+Serial Old这2个组合声明废弃,在JDK9已经完全移除该组合。
    4. (绿色虚线)JDK 14中,已经弃用了Parallel Scavenge和SerialOld GC组合
    5. (青色虚线)JDK 14中,已经删除CMS垃圾回收器

    3、垃圾回收器详解

    3.1、Serial回收器:串行回收

    • Serial收集器是最基本的垃圾收集器,在JDK 1.3之前回收新生代的唯一选择。
    • Serial收集器作为HotSpot中Client模式下的默认新生代垃圾h收集器。
    • Serial收集器采用复制算法、串行回收和“Stop-the-World”机制的方式进行内存回收。
    • 除了年轻代,Serial收集器还提供用于老年代垃圾收集的Serial Old收集器。Serial Old 收集器同样采用串行回收和“Stop the World”机制,内存回收算法采用的是标记-压缩算法。
    • Serial Old 是运行在Client模式下默认的老年代垃圾回收器
    • Serial Old 在Server模式下主要有2个用途:①和新生代的Parallel Scavenge配合使用 ②作为老年代CMS收集器的后备垃圾收集方案。
      如图,Serial、Serial Old回收器垃圾回收过程:
      image
      Serial收集器作为一个单线程的垃圾回收器,说明它只能使用一个cpu或一条收集线程进行垃圾收集工作,而且它必须暂停其他所有的工作线程,直到它收集工作结束。

    优点:没有线程的交互开销,专心垃圾收集,获取最高的单线程收集效率。
    缺点:暂停工作线程,系统容易出现卡顿。

    3.2、ParNew回收器:并行回收

    • ParNew收集器是Serial收集器的多线程版本,可以有多个垃圾回收线程同时运行进行回收,这样Stop The World的世界会更短,但实际上用户线程同样需要暂停。

    • ParNew收集器在年轻代中,采用的也是复制算法、"Stop The World"机制。

    • ParNeW是很多JVM运行在Server模式下新生代的默认垃圾收集器。

    image

    • 对于新生代而言,回收次数频繁,使用并行方式高效、
    • 对于老年代而言,回收次数少,使用串行方式节省资源。
    • ParNew收集器是基于并行回收,其回收效率也不一定会比Serial收集器要高。ParNew是运行在多CPU环境下,可以充分利用多CPU、多核心的硬件资源优势,更加快速地完成垃圾收集,提升程序的吞吐量。
    • 但是在单个CPU环境下,ParNew收集器不比Serial收集器更高效,因为Serial是基于串行回收的,不需要频繁地在cpu上做任务切换,可以有效避免多线程交互而产生的额外开销。
    • 除了Serial以外,ParNew GC还可以和CMS收集器配合工作
    • 可以通过-XX:+UseParNewGC手动指定使用ParNew收集器进行执行内存回收任务。它代表的是年轻代使用并行收集器,不影响老年代。
    • -XX:ParallelGCThreads 限制线程数量,默认开启和CPU数据相同的线程数。

    3.3、Parallel Scavenge回收器:吞吐量优先(Java 8默认的垃圾收集器)

    • Parallel Scavenge收集器采用复制算法、并行回收和"Stop The World"机制
    • 可控制吞吐量,可以自行调节参数来控制以及一个自适应的策略。
    • 和ParNew收集器不同,Parallel Scavenge收集器的目标是为了达到一个可控制的吞吐量。
    • Parallel收集器在JDK 1.6时提供了用于执行老年代垃圾收集的Parallel Old收集器,用来代替老年代的Serial Old 收集器。
    • Parallel Old 收集器采用的是标记-压缩算法,但是同样也是基于并行回收和"Stop The World"机制。

    • 参数配置:
    • -XX:+UseParallelGC 手动指定年轻代使用Parallel并行收集器执行内存回收任务。
    • -XX:+UseParallelOldGC 手动指定老年代都是使用并行回收收集器
      分别适用于新生代和老年代,在jdk 8中默认开启。上面2个参数,默认开启一个,另一个也会被开启(互相激活)
    • -XX:ParallelGCThreads 设置年轻代并行收集器的线程数。一般来说,最好和CPU的数量相等,避免过多的线程数量影响垃圾收集性能。
      默认情况下,当CPU数量小于8,ParallelGCThreads的值等于cpu数量。当CPU的数量大于8时,ParallelGCThreads的值等于3+[5*cpu_count/8]
    • -XX:MaxGCPauseMillis 设置垃圾收集器最大停顿时间(即STW的时间,单位是毫秒)
      为了尽可能把停顿时间控制在MaxGCPauseMillis以内,收集器在工作时会调整Java堆大小或者其他参数。而对于用户来说,该停顿时间越短,体验越好,但是在服务器端,更加注重高并发和整体的吞吐量。所以服务器端适合Parallel,进行控制。使用该参数需要谨慎!!!!
    • XX:GCTimeRatio 垃圾收集时间占总时间的比例,用于衡量吞吐量大小。
      取值范围(0-99),默认值99,也就是垃圾回收时间不超过1%。与前一个-XX:MaxGCPauseMillis参数有一定矛盾性,暂停时间越长,Radio参数就容易超过限定的比例
    • -XX:+UseAdaptiveSizePolicy 设置Parallel Scavenge收集器具有自适应调节策略
      在该模式下,年轻代的大小、Eden和Survivor的比例、晋升老年代的对象等参数会被自动调整,已达到在堆大小、吞吐量和停顿时间之间的平衡点
      在手动调优比较困难的场合,可以直接使用这种自适应的方式,仅指定虚拟机的最大堆、目标的吞吐量(GCTimeRatio)和停顿时间MaxGCPauseMillis,让虚拟机自己完成调优工作

    image

  • 相关阅读:
    springboot+mybatisplus使用xml找不到mapper的解决办法
    PDF转换成Word文档
    Mybatis-Plus增删改查
    Redis 常用命令
    Java 获取两个List<String>中不同的数据
    controller 返回界面 中文乱码
    Navicat已经成功连接,密码忘记的解决方案
    List数组指定切割
    xml字符串转换成Map
    Java 前一个月的最后一天日期计算
  • 原文地址:https://www.cnblogs.com/linuxk/p/16445307.html
Copyright © 2020-2023  润新知