问十六:你了解哪些垃圾收集器呢?

整体结构:

 

1.Serial收集器

-XX:+UseSerialGC 复制算法

1.是一个单线程收集器,只会使用一个CPU或一条收集线程去完成垃圾收集工作

2.进行垃圾收集时,必须暂停其他所有的工作线程,直至Serial收集器收集结束为止(“Stop The World”)

3.是HotSpot虚拟机运行在Client模式下的默认的新生代收集器

4.与其他收集器的单线程相比更加简单高效,对于限定单个CPU的环境来说,Serial收集器由于没有线程交互的开销,因此可以获得更高的单线程收集效率

 

2. ParNew收集器

-XX:+UseParNewGC 复制算法

1.ParNew收集器就是Serial收集器的多线程版本,它是一个新生代收集器

2.除了使用多线程进行垃圾收集外,其余行为与Serial收集器完全相同,是许多运行在Server模式下的虚拟机中首选的新生代收集器目前只有它能与CMS收集器(老年代收集器)配合工作

3.ParNew在单cpu下性能比Serial差,但在多cpu下好,其默认开启与cpu数量相同的线程来进行垃圾收集

 

3.Parallel 收集器

-XX:+UseParallelGC 复制算法

-XX:+UseParallelOldGC 标记-整理算法

1.Parallel Scavenge收集器也是一个并行的多线程新生代收集器

2.用复制算法,目的是为了达到一个可控制的吞吐量

 

1.Parallel Old收集器是用在老年代的收集器,使用标记整理算法

吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值:吞吐量=运行用户代码的时间/(运行用户代码时间+垃圾收集时间)

 

4. CMS收集器

-XX:+UseConcMarkSweepGC 标记-清除算法

概述:

CMS,全称Concurrent Mark and Sweep,用于对年老代进行回收,目标是尽量减少应用的暂停时间,减少full gc发生的机率,利用和应用程序线程并发的垃圾回收线程来标记清除年老代

CMS并非没有暂停,而是用两次短暂停来替代串行标记整理算法的长暂停。


收集周期:

1) Initial Mark 初始标记

这个阶段的任务是标记老年代中被GC Roots直接可达和被年轻代对象引用的对象,这个阶段也是第一次STW发生的阶段

2) Concurrent Mark 并发标记

这个阶段主要是通过从初始标记阶段中寻找到的标记对象开始,遍历老年代并且标记所有存活着的对象

需要注意的是,并非所有在老年代中存活的对象都会被标记,因为程序在标记期间可能会更改引用(比如图中的Current obj,它是并发标记阶段伴随着程序一起被删除了引用的对象)

这个阶段与应用程序共同运行

3) Concurrent Preclean 执行预清理   

注: 相当于两次 concurrent-mark. 因为上一次concurrent-mark耗时较长,会有从新生代晋升到老年代的对象出现,将其清理掉

这也是一个并发阶段,与应用程序的线程并行执行。并发标记阶段与应用程序同时运行时,一些对象的引用可能会被改变一旦这种情况发生,JVM就会标记堆上面的这块包含了变化对象的区域这个堆的区域被称为"Card",这种方式被称为"Card Marking"

在这个阶段,这些脏对象将会被声明,并且这些对象能够到达的对象也会被标记。这些Card将会在上面的工作完成之后被清理掉

此外,还将执行一些必要的整理和重新标记阶段的准备工作。

4) Concurrent Abortable Preclean 执行可中止预清理  

这个阶段也是和程序线程并发执行的。它的工作就是尽可能地进行清理工作,以减少重新标记阶段的任务即减少了STW的停顿时间

这个阶段的持续时间取决于很多因素,因为它需要不断地做一些相同的工作,直到满足某个终止条件为止(比如一定的迭代次数、一定的有效工作量、一定的时间等等)

5) Final Remark 重新标记

这个阶段是第二次,也是最后一次STW。这个阶段的目的是标记在老年代中被标记的所有存活下来的对象。

6) Concurrent Sweep 并发清除

移除未使用的对象,并且回收其占用的空间。

7) Concurrent Reset 并发重置

重置CMS算法内部的数据结构,为下一个周期做准备

参考文档:https://plumbr.io/handbook/garbage-collection-algorithms-implementations/concurrent-mark-and-sweep


CMS减少停顿的原理:

标记过程分三步:并发标记是最主要的标记过程,而这个过程是并发执行的,可以与应用程序线程同时进行初始标记重新标记虽然不能和应用程序并发执行,但这两个过程标记速度快,时间短,所以对应用程序不会产生太大的影响

最后并发清除的过程,也是和应用程序同时进行的,避免了应用程序的停顿

CMS的特点:减少了应用程序的停顿时间,让回收线程和应用程序线程可以并发执行,它的回收并不彻底。因此CMS回收的频率相较其他回收器要频繁的回收将影响应用程序的吞吐量,空间碎片多

CMS何时开始?

cms gc 通过一个后台线程触发,该线程随着堆一起初始化,触发机制是默认每隔2秒判断一下当前老年代的内存使用率是否达到阈值,如果高于某个阈值的时候将激发CMS

两次STW的原因:

当虚拟机完成两次标记后,便确认了可以回收的对象。但是,垃圾回收并不会阻塞程序的线程,如果当GC线程标记好了一个对象的时候,此时程序的线程又将该对象重新加入了GC-Roots的“关系网”中,当执行二次标记的时候,该对象也没有重写finalize()方法,因此回收的时候就会回收这个不该回收的对象

为了解决这个问题,虚拟机会在一些特定指令位置设置一些“安全点”,当程序运行到这些“安全点”的时候就会暂停所有当前运行的线程(Stop The World 所以叫STW),暂停后再找到“GC Roots”进行关系的组建,进而执行标记和清除。

这些特定的指令位置主要在:

1、循环的末尾

2、方法临返回前 / 调用方法的call指令后

3、可能抛异常的位置

 

5.G1收集器

-XX:+UseG1GC 复制+标记-整理算法

概述:

是jdk1.7以后推出的回收器,试图取代CMS回收器

不同于其他的回收器,G1将堆空间划分成了互相独立的区块每块区域既有可能属于老年代、也有可能是新生代,并且每类区域空间可以是不连续的(对比CMS的老年代和新生代都必须是连续的

这种将老年代区划分成多块的理念源于:当并发后台线程寻找可回收的对象时、有些区块包含可回收的对象要比其他区块多很多。虽然在清理这些区块时G1仍然需要暂停应用线程、但可以用相对较少的时间优先回收包含垃圾最多区块。

 

G1相对CMS回收器来说区别在于:

1、CMS是以获取最短回收停顿时间为目标,G1是面向服务端应用的垃圾收集器

1、因为划分了很多区块,回收时减小了内存碎片的产生

2、G1适用于新生代和老年代,而CMS只适用于老年代

3、CMS使用标记清除算法,G1整体上看是“标记-整理”,局部看是“复制”

 

 

全部评论

相关推荐

11-24 00:11
已编辑
广东工业大学 算法工程师
避雷深圳  yidao,试用期 6 个月。好嘛,试用期还没结束,就直接告诉你尽快找下一家吧,我谢谢您嘞
牛客75408465号:笑死,直属领导和 hr 口径都没统一,各自说了一些离谱的被裁理由,你们能不能认真一点呀,哈哈哈哈哈😅😅😅
点赞 评论 收藏
分享
accaacc:2到4k,不是2k到4k,所以年薪是30块
点赞 评论 收藏
分享
头像
10-14 23:01
已编辑
中国地质大学(武汉) Java
CUG芝士圈:虽然是网上的项目,但最好还是包装一下,然后现在大部分公司都在忙校招,十月底、十一月初会好找一些。最后,boss才沟通100家,别焦虑,我去年暑假找第一段实习的时候沟通了500➕才有面试,校友加油
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
11-21 17:16
科大讯飞 算法工程师 28.0k*14.0, 百分之三十是绩效,惯例只发0.9
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务