目标:
1.JVM垃圾收集器有哪几种?
2.CMS垃圾收集器回收步骤。
一、JVM常见的垃圾回收器
为什么垃圾回收的时候需要STW?
标记垃圾的时候,如果不STW,可能用户线程就会不停的产生垃圾。
1.1 单线程收集
Serial和SerialOld使用单线程收集
开启参数 -XX:+UserSerialGC
1.2 多线程收集
ParallaNew和ParallaOld采用的多线程收集。
-XX:MaxGCPauseMillis=time 控制垃圾收集的暂停时间。
-XX:GCTimeRatio: 默认99,垃圾回收时间占总时间的大小。吞吐量优先。
PS组合(Paralla Scavenge+ Paralla Old组合),吞吐量优先,空间自适应调整。
200M空间不足,GC后自适应调整为250M。
扩容:伴随着GC,新生代自动扩容。两个参数:
MaxHeapFreeRatio: GC后,最大堆空间剩余比例,缩容。
MinHeapFreeRatio: GC后,最小堆空间剩余空间大小。扩容
堆空间设置为-Xms == -Xmx, 保持一个稳定的堆。
吞吐优先--》响应优先
1.3 响应优先垃圾回收器
CMS是第一款响应优先的垃圾回收器。
二、CMS垃圾回收器
CMS是针对老年代的垃圾收集器。
2.1 初始标记
- 只标记与GC Roots直接相关连的对象;
- 需要STW
标记对象不是很多。
2.2 并发标记
继续完成标记,对并发标记的对象,继续进行标记,这是比较耗时的操作,不进行STW。
2.3 重新标记
并发标记因为是并发执行的,此时用户线程可能重新修改了标记对象,因此需要STW,暂停用户线程,对 并发标记阶段变化的对象进行重新标记。
2.4 并发清除
CMS为什么能够做到并打清除呢?
因为CMS采用的是标记清除算法,清理垃圾时存活对象不会发生移动,因此引用地址没有变化,不需要进行STW。
2.5 预清理和并发可中断预清理
在并发标记和重新标记中,插入两个阶段:预清理和并发可中断预清理。
为什么能够插入?
并发标记不暂停(STW),我们要尽量缩短STW时间(重新标记时间),因此在并发阶段做的事情越多越好。
预清理控制参数:CMSPreClieaningEnabled CMS默认开启的。
2.5.1 预清理
1)如果新生代创建的对象A,在老年代存在跨代引用没有标记的对象B,那么B需要修改为存活状态。
2)老年代应用对象发生变化,需要标记为dirty,进行重新标记。记录类似与卡表的结构。
2.5.2 并发可中断预清理
控制参数 CMSScheduleRemarkEdenSizeThreshold 2M,Eden区存活对象达到2M。
并发标记阶段,如果From区和To区的引用对象发生跨代引用。老年代应用对象发生变化,需要标记为dirty,进行重新标记。
可中断。中断条件: