JVM-垃圾回收器的相关概述(不断补充完善)

1、GC垃圾回收器的分类

1.1、按线程数量分

在这里插入图片描述

串行垃圾回收器
同一个时间段内只允许一个CPU用于执行垃圾回收,此时工作线程暂停,直到GC完毕。
在这里插入图片描述
优点:
1、简单而高效(与其他单线程收集器比),由于没有与线程交互,只关注垃圾回收本身。
2、用户桌面应用场景中,可用内存不大,可以在较短的时间内完成垃圾回收

并行垃圾回收器
同一个时间段内允许多个CPU同时执行垃圾回收,提升了吞吐量。
在这里插入图片描述
在这里插入图片描述

相同点:
两者采用的方式任然是独占式进行垃圾回收,即STW。


1.2、按工作模式

在这里插入图片描述
独占式垃圾回收器
一旦运行,随即中断所有其他工作线程,直到收集结束
并发式垃圾回收器
允许垃圾回收线程和用户线程交替工作,减少停顿时间


1.3、按碎片处理方式

压缩式垃圾回收器
非压缩式垃圾回收器
区别在于是否在垃圾回收后对对象进行整理,消除垃圾回收后产生的碎片。


1.4、按工作空间划分

年轻代垃圾回收器
老年代垃圾回收器


2、评估垃圾回收器的主要指标

1、吞吐量:用户代码执行的时间占总运行时间的比例
2、暂停时间:STW的时间
3、占用的内存:Java堆中占用内存的大小


3、七大经典垃圾回收器(重点)

概述

#串行,并行,并发回收器的大概执行流程预览图:这里是引用
#垃圾收集器与垃圾分代之间的关系:
其中G1收集器是属于整堆回收。JDK9之后默认使用的垃圾回收器在这里插入图片描述
#垃圾收集器之间的组合关系–截至到JDK14为止
在这里插入图片描述
在这里插入图片描述
查看默认的垃圾回收器:
JPS
jinfo -flag 进程号
在这里插入图片描述


3.1、串行回收器

3.1.1、Serial

1、采用的是复制算法
2、针对的是新生代
3、采用的是串行回收和STW机制

3.1.2、Serial Old

1、采用的是标记压缩算法
2、针对的是老年代
3、采用的是串行回收和STW机制


3.2、并行回收器

3.2.1、ParNew

1、Parallel New,从字面上便知道它是并行的,针对新生代的。
2、采用复制算法
3、除了采用并行的回收垃圾方式,与Serial垃圾回收器无异

3.2.2、Parallel Scavenge

1、吞吐量优先
2、采用复制算法
3、采用并行回收和STW
4、自适应是Parallel Scavenge和ParNew一个重要区别
5、适合使用在后台运算不太需要很多交互的任务
6、在程序吞吐量优先的场景,Parallel 和 Parallel Old收集器组合,在Server模式下回收性能不错,因此在JDK8中,默认是此垃圾回收器。

3.2.2、Parallel Old

1、 采用标记压缩算法
2、采用并行回收和STW


3.3、并发回收器

3.3.1、CMS

在这里插入图片描述

1、Concurrent-Mark-Sweep,主要的特点可以总结为低延迟
2、采用标记-清除算法和STW
3、针对老年代,只能配合ParNew或者Serial工作
4、四个阶段:
#初始标记阶段:
在这个阶段会短暂STW暂停所有线程,但这个时间非常短,主要目的是在这个阶段标记出GC Roots 能直接关联的对象
#并发标记阶段:
在这个阶段从GC Roots直接关联的对象开始遍历整个对象图的过程,对可达对象进行标记,此过程是不需要暂停用户线程,耗时较久。
#重新标记阶段:
由于在并发标记的时候没有暂停用户线程,那么在对象的调用途中引用关系可能发生变化,为了更加确保回收对象的正确性,在这个阶段进行短暂的STW,修正并发标记中引用关系发生变化的对象的标记。即对已经被标记的对象进行修复
#并发清理阶段:
通过标记清除算法对垃圾进行回收,此过程是并发的,不会影响用户体验。

简单总结:
1、 由于在4个阶段中,实际的垃圾回收的过程是并发的,因此认为它是非独占式的。
2、在使用CMS垃圾回收器的时候,应该确保应用程序有足够的内存可用。因为CMS垃圾回收器如果等到内存块满了的时候再进行回收,由于其本身也属于一个线程会占用部份内存,有可能就会导致内存溢出。因此,当堆内存使用率达到一定阈值的时候,便开始回收。要是CMS运行期间内存空间不足无法满足程序需要,会产生"concurrent mode failure"失败,启动后备方案临时启动Serial Old对老年代进行垃圾回收
3、为什么使用标记清理算法而不是标记清除算法的原因是因为我们对垃圾进行回收的时候用户线程是并发执行的,如果我们用标记压缩算法的话,会改变对象的引用地址,对并发的其他用户线程造成影响。
4、会产生内存碎片,如果此时来了大对象而没地方存放,提前触发FULL GC
5、占用了部分线程,降低了系统的吞吐量
6、在并发标记阶段由用户线程和GC线程并发执行,如果在并发标记阶段产生新的垃圾,CMS无法对这些垃圾对象进行标记,最终会导致这些新产生的垃圾对象没有被及时回收,从而只能在下一次执行GC时释放这些之前未被回收的内存空间
7、JDK9往后已经不再使用,JDK14以移除

3.3.2、G1(重点):区域化分代式

#前言:
在上面的各种收集器中,各有各的优点,Parallel回收器可以满足高吞吐量,通过自适应的调整优化策略。CMS可以减少STW时间,给用户线程带来良好的用户体验。在需求快速变化的时代,经常会造成STW的GC又跟不上时代的变化,因此对新的垃圾回收器的研发是迫在眉睫的,因此G1垃圾回收器诞生了。
#官方定位:
延迟可控的情况下提高吞吐量–全能型的垃圾回收器
#4大优势:
1、并行与并发:
并行:在GC阶段可以有多个GC线程同时工作,有效利用CPU多核计算能力。此过程用户线程STW。
并发:部分工作可以与应用程序同时进行,因此GC阶段并不会造成完全的阻塞。
2、分代收集:
从大体上看仍然是分代收集,因为还会区分老年代,新生代,新生代还是有伊甸园区,幸存者区。但是从堆得结构上来看,它不在要求堆内存是连续空间是连续的,也不再坚持固定大小和数量,而是将堆分成了若干个区域,如下图所见:
在这里插入图片描述 其中,Humongous内存区域,如图中的H块。主要用于存储大对象,如果超过1. 5个region,就放到H。如果一个H区装不下一个大对象,那么G1会寻找连续的H区来存储,不得已的时候会启动Full GC。
3、空间整合:
内存的回收是以一个个区域为单位的,而不是以代为单位的。每个区域之间采用的是复制算法,而总体对每个区域采用的又是标记-压缩算法。从而达到即提高了回收效率,也实现了碎片化整理的功能。
4、可预测停顿的时间:
让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒。
#补充
G1根据每个区域里面的垃圾价值大小在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的区域。保证了G1 收集器在有限的时间内可以获取尽可能高的收集效率。
#缺点:
G1需要占用额外的内存空间,主要适合大堆,低延迟要求下

#参数设置:
-XX:+UseG1GC 手动指定使用G1收集器执行内存回收任务。
-XX:G1HeapRegionSize 设置每个Region的大小。值是2的幂,范围是1MB 到32MB之间,目标是根据最小的Java堆大小划分出约2048个区域。默认是堆内存的1/2000。
-XX:MaxGCPauseMillis 设置期望达到的最大Gc停顿时间指标(JVM会尽力实现,但不保证达到)。默认值是200ms
-XX:ParallelGCThread 设置STW工作线程数的值。最多设置为8
-XX:ConcGCThreads 设置并发标记的线程数。将n设置为并行垃圾回收线程数(ParallelGCThreads)的1/4左右。
-XX:Ini tiatingHeapOccupancyPercent 设置触发并发GC周期的Java堆占用率阈值。超过此值,就触发GC。默认值是45。

#G1垃圾回收的过程
在这里插入图片描述
一、当Eden区内存空间满了,触发Young GC,此时对于年轻代的回收是一个并行的独占式的回收器,在此过程中会STW,同时将Eden区活着的对象复制到幸存者区,也有可能直接进入老年区(如果对象比较大的情况下活着age达到了15);
二、当堆内存使用达到阈值45%(默认),触发并发标记过程,对所有可达的对象进行标记。
三、标记完成后进行混合回收,但是在这里老年代的GC回收器回收并不是全部回收,它回收的是一个个价值比较大的region,而不像年轻代回收所有的没有用的对象。

#记忆集与写屏障
我们知道,每一个区域的对象不可能是孤立的,一个区域中的对象可能被多个其他区域的对象所引用,举个例子,假如Eden区有一对象被老年区所引用,我们需要判断Eden区的对象是否是垃圾,那我们需要遍历Eden区看看有没有被其他同为Eden区的对象所引用,同时再遍历老年区中看看是否有其他对象引用了Eden区中的该对象,而我们知道标记阶段会进行STW操作,这样会导致STW时间过长,从而影响用户体验。记忆集与写屏障很好的解决了这个问题,用一张图来说:
在这里插入图片描述
通过上面这种图我们可以看到,Region1引用了Region2,Region也引用了Retion2,如此引的位置我们把它记录在Rset中,这便是记忆集。每次Reference类型数据写操作时,都会产生一个Write Barrier暂时中断操作,这个Write Barrier便是写屏障。随后检查将要写入的引用指向的对象是否和该Reference类型数据在不同的Region,即判断该对象的引用是否来自于自己的区域,如果是则不写入记忆集,如果不是则记录下引用对象的位置。当进行垃圾收集时,在GC根节点的枚举范围加入Remembered Set,就可以保证不进行全局扫描,也不会有遗漏。


4、经典垃圾回收器小结

各垃圾回收器小结:这里是引用

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值