十七、垃圾回收器


1.GC分类与性能指标

GC分类:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
评估GC的性能指标:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.不同垃圾回收器概述

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

3.Serial回收器:串行回收

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

4.ParNew回收器:并行回收

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

5.Parallel回收器:吞吐量优先

  • HotSpot的年轻代中除了拥有ParNew收集器是基于并行回收的以外,Parallel Scavenge收集器同样也采用了赋值算法、并行回收和”Stop the World"机制。

  • 那么Parallel收集器的出现是否多此一举?
    》和ParNew收集器不同,Parallel Scavenge收集器的目标则是达到一个可控制的吞吐量(Throughout),它也被称为吞吐量优先的垃圾收集器。
    》自适应调节策略也是Parallel Scavenge与ParNew一个重要区别。

  • 高吞吐量则可以高效地利用CPU时间,尽快完成程序的运算任务,主要适合在后台运算而不需要太多交换的任务。因此,常见在服务器环境中使用。例如,那些执行批量处理、订单处理、工资支付、科学计算的应用程序。

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

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

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

  • 在Java8中,默认是此垃圾收集器。

参数设置:

  • -XX:+UseParallelGC 手动指定年轻代使用Paprallel并行收集器执行内存回收任务。
  • -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:GCTimeRatio 垃圾收集时间占总时间的比例(=1/(N+1))。用于衡量吞吐量的大小。
    》取值范围(0,100)。默认值99,也就是垃圾回收时间不超过1%。
    》与前一个-XX:MaxGCPauseMills参数有一定矛盾性。暂停时间越长,Radio参数就容易超过设定的比例。
  • -XX:+UseAdaptiveSizePolicy 设置Parallel Scavenge收集器具有自适应调节策略。
    》在这种模式下,年轻代的大小、Eden和Survivor的比例、晋升老年代的对象年龄等参数会被自动调整,以达到在堆大小、吞吐量和停顿时间之间的平衡点。
    》在手动调优比较困难的场合,可以直接使用这种自适应的方式,仅指定虚拟机的最大堆,目标的吞吐量(GCTimeRatio)和停顿时间(MaxPauseMills),让虚拟机自己完成调优工作。

6.CMS回收器:低延迟

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

  • 尽管CMS收集器采用的是并发回收(非独占式),但是在其初始化标记和再次标记这两个阶段中仍然需要执行“Stop-the-world"机制暂停程序中的工作线程,不过暂停时间并不会太长,因此可以说明目前所有的垃圾收集器都做不到完全不需要”Stop-the-World“,只是尽可能地缩短暂停时间。
  • 由于最耗费时间的并发标记与并发清除阶段都不需要暂停工作,所有整体的回收是低停顿的。
  • 由于在垃圾收集阶段用户线程没有中断,所以在CMS回收过程中,还应该确保应用程序用户线程有足够的内存可用。因此,CMS收集器不能像其他收集器那样等到老年代几乎完全被填满了再进行收集,而是当堆内存使用率达到某一阈值时,便开始进行回收,以确保应用程序在CMS工作过程中依然有足够的空间支持应用程序运行。要是CMS运气期间预留的内存无法满足需要,就会出现一次”Concurrent Mode Failure"失败,这时虚拟机将启动后备预案:临时启用Serial Old收集器来重新进行老年代的垃圾收集,这样停顿时间就很长了。
  • CMS收集器的垃圾收集算法采用的是标记-清除算法,这意味着每次执行完内存回收后,由于被执行内存回收的无用对象所占用的内存空间极有可能是不连续的一些内存块,不可避免地将会产生一些内存碎片。那么CMS在为新对象分配内存空间时,将无法使用指针碰撞技术,而只能选择空闲列表执行内存分配。
  • CMS的优点:
    》并发收集
    》低延迟
  • CMS的弊端:
  1. 会产生内存碎片,导致并发清除后,用户线程可用的空间不足。在无法分配大对象的情况下,吧,不得不提前触发Full GC.
  2. CMS收集器对CPU资源非常敏感。在并发阶段,它虽然不会导致用户停顿,但是会因为占用了一部分线程而导致应用程序变慢,总吞吐量会降低。
  3. CMS收集器无法处理浮动垃圾。可能出现”Concurrent Mode Failure"失败而导致另一次Full GC的产生。在并发标记阶段由于程序的工作线程和垃圾收集线程是同时运行或者交叉运行的,那么在并发标记阶段如果产生新的垃圾对象,CMS将无法对这些垃圾对象进行标记,最终会导致这些新产生的垃圾对象没有及时回收,从而只能在下一次执行GC时是否掉这些之前未被回收的内存空间。

参数设置:
在这里插入图片描述

在这里插入图片描述

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

7.G1回收器:区域化分代式

为什么名字叫做Garbaeg First(G1):

  • 因为G1是一个并行回收器,他把堆内存分割为很多不相关的区域(Region)(物理上不连续的)。使用不同的Region来表示Eden、幸存者0区、幸存者1区、老年代等。
  • G1 GC有计划地避免在整个java堆中进行全区域的垃圾收集。G1跟踪各个Region里面的垃圾堆积的价值大小(回收所获得的空间大小以及回收所需时间经验值),在后台维护一个优秀队列,,每次根据允许的收集时间,优秀回收价值最大的Region。
  • 由于这种方式的侧重点在于回收垃圾最大量的区间(Region),所以给G1一个名字:垃圾优秀(Garbage First)。
  • G1是一款面向服务端应用的垃圾收集器,主要针对配备多核CPU及大容量内存的机器,以极高概率满足GC停顿时间的同时,还兼具高吞吐量的性能特征。

为什么还要发布Garbage First(G1) GC?

  • 原因在于应用程序所应对的业务越来越大、复杂、用户越来越多,而经常造成STW的GC又跟不上实际的需求,所以才会不断地尝试对GC进行优化。
  • 与此同时,为了适应现在不断扩大的内存和不断增加的处理器数量,进一步降低暂停时间(pause time),同时兼顾良好的吞吐量。,
  • 官方给G1设定的目标是在延迟可控的情况下获得尽可能高的吞吐量,所以才担当起“全功能收集器”的重任与期望。

G1收集器的特点(优势):

与其他GC收集器相比,G1使用了全新的分区算法,其特点如下所示:

  • 并行与并发:
    》并行性:G1在回收期间,可以多个GC线程同时工作,有效利用多核计算能力。此时用户线程STW.
    》并发性:G1拥有与应用程序交替执行的能力,部分工作可以和应用程序同时执行,因此,一般来说,不会在整个回收阶段发生阻塞应用程序的情况。
  • 分代收集
    》从分代上看,G1依然属于分代型垃圾回收器,他会区分年轻代和老年代,年轻代依然有Eden区和Survivor区。但从堆的结构上看,它不要求整个Eden区、年轻代或者老年代都是连续的,也不再坚持固定大小和固定数量。
    》将对空间分为若干个区域(Region),这些区域中包含了逻辑上的年轻代和老年代。
    》和之前的各类回收器不同,它同时兼顾年轻代和老年代。对比其他回收器,或者工作在年轻代、或者工作在老年代。
    在这里插入图片描述
  • 空间整合
    》CMS:"标记-清除“算法、内存碎片、若干次GC后进行一次碎片整理。
    》G将内存划分为一个个的Region。内存的回收是以Region作为基本单位的。Region之间是赋值算法,但整体上实际可看作是标记-压缩(Mark-ComPact)算法,两种算法都可以避免内存碎片。这种特性有利于程序长时间运行,分配大对象时不会因为无法找到连续内存空间而提前触发下一次GC。尤其是当Java堆非常大时,G1的优势更加明显。
  • 可预测的停顿时间模型(即:软实时soft real-time)
    这是G1相对于CMS的另一大优势,G1除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间段内,消耗在垃圾收集上的时间不得超过N毫秒。
    》由于分区的原因,G1可以只选取部分区域进行内存回收,这样缩小了回收的范围,因此对于全局停顿情况的发生也能得到较好的控制。
    》G1跟踪各个Region里面的垃圾堆积的价值大小(回收所获得的空间大小以及回收所需时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的Region。保证了G1收集器在有限的时间内可以获取尽可能高的收集效率。
    》相比于CMS GC,G1未必能做到CMS在最好情况下的延迟停顿,但是最差情况要好很多。

G1回收器的参数设置

在这里插入图片描述

G1回收器的常见操作步骤:

在这里插入图片描述
在这里插入图片描述
分区Region:化整为零:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

G1回收器垃圾回收过程:

G1 GC的垃圾回收过程主要包括如下三个环节:

  • 年轻代GC(Young GC)
  • 老年代并发标记过程(Concurrent Marking)
  • 混合回收(Mixed GC)
  • (如果需要,单线程、独占式、高强度的Full GC还是继续存在的。它针对GC的评估失败提供了一种失败保护机制,即强力回收。)
    在这里插入图片描述
  • 应用程序分配内存,当年轻代的Eden区用尽时开始年轻代回收过程;G1的年轻代收集阶段是一个并行的独占式收集器。在年轻代回收期,G1 GC暂停所有应用程序线程,启动多线程执行年轻代回收。然后从年轻代区间移动存活对象到Survivor区间或者老年区间,也有可能是两个区间都会涉及。
  • 当堆内存使用达到一定值(默认45%)时,开始老年代并发标记过程。
  • 标记完成马上开始混合回收过程。对于一个混合回收期,G1 GC从老年区移动存活对象到空闲区间,这些空闲区间也就成为了老年代的一部分。和年轻代不同,老年代的G1回收器和其他GC不同,G1老年代回收器不需要整个老年代被回收,一次只需要扫描/回收一小部分老年代的Region就可以了。同时,这个老年代Region是和年轻代一起被回收的。

G1回收器垃圾回收过程:Remembered Set

  • 一个对象被不同区域引用的问题。
  • 一个Region不可能是孤立的,一个Region中的对象可能被其他任意Region中对象引用,判断对象存活时,是否需要扫描整个Java堆才能保证准确?
  • 在其他的分代收集器,也存在这样的问题(而G1更加突出)
  • 在回收新生代也不得不同时扫描老年代?
  • 这样的话会降低Minor GC的效率。
  • 解决办法:
    》无论G1还是其他分代收集器,JVM都是使用Remembered Set来避免全局扫描。
    》每个Region都有一个对应的Remembered Set.
    》每次Reference类型数据写操作时,都会产生一个Write Barrier暂时中断操作。然后检查将要写入的引用对象是否和该Reference类型数据在不同的Region(其他收集器:检查老年代对象是否引用了新生代对象);如果不同,通过CardTable把相关引用信息记录到引用指向对象的所在Region对应的Remembered Set中。
    》 当进行垃圾收集时,在GC根节点的枚举范围加入Remembered Set;就可以保证不进行全局扫描,也不会有遗漏。

G1垃圾回收过程的详细说明:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
G1回收器优化建议:
在这里插入图片描述

8.7中经典的垃圾回收器总结与调优建议

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

9.GC日志分析

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值