第一次如何记住繁杂的垃圾收集器
第一次如何记住繁杂的垃圾收集器
首先在学习垃圾收集器之前,你一定要知道JVM内存模型和常见的垃圾回收算法。
连线代表相互之间可以配合使用,G1则在新生代和老年代都使用;
简单介绍
垃圾收集器可以分为串行(Ser)、并行(par)、**响应时间优先(CMS)**来记。
年轻代:
- 最早出现的是单线程的 — > Serial
- 并行的 ----- > ParNew
- 吞吐量优先的(不关注单次GC时间) ----- > Parallel Scavenge(一般客户端)
老年代:
- Serial Old ---- 和年轻代的 Serial 搭配使用
- CMS(G1出现之前广泛使用) ---- 年轻代ParNew
- Parallel Old ---- 年轻代Parallel Scavenge
年轻代的Minor GC一般时间比较短,我们更关注时间较长的老年代回收;
Serial Old串行和Parallel Old关注吞吐率的故它们单次执行GC的时间可能过长;而CMS则关注单次GC的时间;
CMS GC过程
CMS收集器是一种以获取最短回收停顿时间为目标的收集器;(在GC过程中,一般用户线程都会有短暂停止,也就是回收时用户线程要停止。CMS的出现是第一个真正意义上实现垃圾收集线程和用户线程同时工作)
我们来看看它的过程:
- 初次标记 : 时间很短,只是标记一些GC Roots能直接关联的对象。(需要Stop the World也就是用户线程不能工作)
- 并发标记 : 标记所有的对象,时间较长, 用户线程未停顿,故可能会产生新的要清理的对象,所有我们来到重新标记。
- 重新标记 : 修正第二步导致标记变动的对象的标记记录。 需要Stop the World (时间比第一步稍长,但是远比第二步短,所以总共来说并没有Stop the World 特别长的时间,用户体验nice)
- 并发清除: 清除被标记的对象 — 采用标记清除算法 (用户引用的对象还在原来的位置,故可以并发)。
在老年代Serial Old和Parallel Old都是采用的标记整理算法(不会产生内存碎片)
带并发两个字的当然代表其收集器线程和用户线程同时工作,其他两个则需要Stop the world
CMS缺点
对于cpu核数低的服务器不友好
因为在并发标记和并发清除阶段均是并发执行,CMS默认启动的回收线程数为(cpu核数 + 3) / 4,对于那些核数低于4的战五渣服务器及其不友好;
无法处理浮动垃圾
什么是浮动垃圾?
就是并发标记和并发清除阶段,回收线程和用户线程同时运行时产生的垃圾对象,并且这些垃圾在标记结束以后,CMS无法在档次收集中处理它们只能下一次垃圾收集时再清理;
因为无法处理浮动垃圾,故在垃圾收集之前,不能等老年区满了再收集(会产生浮动垃圾),故要预留一部分空间供并发收集时使用,到底预留多少空间,就是真正难办的地方,预留太多了GC容易被**,预留太少的话可能不够并发收集时产生的新垃圾,这样就会出现并发失败的情况
并发失败后 : 启动后备预案,冻结用户线程,临时用Serial Old来重新收集,这样停顿时间就很长了。故预留多少要根据实际情况来定
产生内存碎片
前面提到CMS并发清除是用的 标记-清除法,那么肯定会产生内存碎片嘛。
可以通过设置 -XX: CMSFullGCsBeforeCompaction(jdk9已废弃)使其在不整理空间的Full GC后,下一次进入Full GC前会先进行碎片整理
G1
地位:垃圾收集器里程碑式的成果;
G1是面向堆内存任何部分进行回收的,内存中哪个地方垃圾最多就进行回收 ---- Mixed GC模式;
在以前,我们一般新生区是内存是一段连续的,老年区也是连续的,而G1开创了一种Region的堆内存布局,分成多个大小相等的独立区域(Region) ,每个Region可能是Eden、Survivor或者老年代空间
并且还有一个特殊的Humongous区域存储大对象(超过Region容量的一半),一般一个Region为1M ~ 32 M
Region内存布局:
每一个Region维护了一个记忆集(key - value形式)解决跨Region引用问题 ---- Rset
每个Region维护两个TAMS指针用来保证收集线程和用户线程互不干扰的运行
G1 GC过程
- 初始标记:标记GC Root 和Root Region(GC Root所在的Region); STW(Stop the world)
- 将Root Region去扫描old区中的Rset是否有Root Region,将其标识 STW
- 并发标记: 只需遍历被第二步标记的即可(遍历范围缩小) — 同CMS。
- 重新标记 : 同CMS,只不过用的SATB(三色标记) ,STW
- 清理(复制清理) : 只选出垃圾较多的地方进行清理。STW
小结
- G1只标记了Rset(跨代引用)和GC Root的Region进行遍历,而CMS是所有对象进行遍历;
- STAB原始快照搜索算法进行重新标记
- 将各个Region回收价值进行排序,根据用户设置的期望停顿来制定回收计划(并不是全部清除);
第一次学习垃圾收集器,有记录错误的地方欢迎指出;