垃圾收集器
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清理整个堆空间包括新生代和老年代