跟叶子猿学习JVM(七)垃圾回收机制(四)——垃圾收集器(serial,serial old,parnew,parallel,parallel old,cms,G1)

                                             垃圾收集器


JDK8默认使用的垃圾回收器是:Parallel Scavenge(新生代) + Serial Old(老年代)


新生代(Serial,ParNew,Parallel)


1.Serial收集器(适用于客户端,即桌面应用)【使用复制算法】

最基本,发展最悠久,单线程垃圾回收,用于新生代的内存垃圾收器。例如:当多个线程在执行时候,如果此时要执行垃圾回收,则将所有线程停掉,开始执行垃圾回收的线程(单个),当垃圾回收执行完毕后,其他线程回复执行。这种方式程序总是会运行一会,暂停一会,用户体验很不好。但是对于单线程,内存占用较小的应用比较合适,即使暂停用户也感知不到。

2.parnew收集器【使用复制算法】

用于新生代的内存垃圾收器,与serial不同的是,垃圾回收时是多线程执行。

3.parallel scavenge收集器【使用复制算法】

用于新生代的内存垃圾收器,工作流程同parnew一样,也是多线程执行,但是更加灵活,因为可以通过指定垃圾收集器最大停顿时间(-XX:MaxGCPauseMillis),来达到我们预期设定的吞吐量大小(-XX:GCTimeRatio)。

吞吐量 = 执行用户代码时间 / (执行用户代码时间 + 垃圾回收占用时间)

吞吐量即CPU用于运行用户代码的时间与CPU消耗的总时间的比值。


老年代(Serial Old,Parallel Old,CMS)


4.Serial Old收集器【使用标记-整理算法】

用于老年代的内存垃圾收器,工作流程同Serial一致,只是工作时使用的算法是标记-整理算法

5.parallel old收集器【使用标记-整理算法】

用于老年代的内存垃圾收器,工作流程同parallel一致,只是工作时使用的算法是标记-整理算法

6.cms收集器(Concurrent Mark Sweep)【使用标记-清除算法】

用于老年代的内存垃圾收器,能够并发收集,低停顿。但是会占用大量的CPU资源,且会因为标记-清除算法而产生大量的内存碎片。

工作步骤:标记(标记与GC Roots直接关联的对象) → 并发标记→重新标记(修改部分并发标记)→并发清除


不区分新生代老年代(G1)


7.G1收集器(Garbage First)【复制,标记-整理算法】内存不区分新生代老年代

除了初始标记阶段,其他阶段都可以选择设置成并发或并行执行

工作步骤:

初始标记(标记与GC Roots直接关联的对象)

→ 并发标记(从GC Roots开始,通过可达性分析法,查找存活对象)

→ 最终标记(修正并发标记阶段由于程序继续运行状态产生变化的对象,并发标记阶段会将对象的状态变化存入Remembered Set Logs表里,最终标记阶段会将Remembered Set Logs的数据合并到Remembered Set中)

→ 筛选回收(将被标记的可回收对象进行回收)


总结

Minor GC清理新生代垃圾

Major GC清理老年代垃圾

Full  GC清理整个堆空间包括新生代和老年代


猜你喜欢

转载自blog.csdn.net/Peacock__/article/details/88896352
今日推荐