jvm的垃圾收集器分为如下几种类型:
串行:Serial,Serial Old
吞吐量优先: parNew, parallel Scavenge, parallel Old
响应时间优先:CMS,G1
Serial收集器
单线程收集器,在进行垃圾收集时,必须暂停其他所有的工作线程,直至Serial收集器收集结束为止(stop the world)。虚拟机运行在Client模式下的默认的新生代收集器
Serial收集器
ParNew收集器
ParNew收集器就是Serial收集器的多线程版本,它也是一个新生代收集器,目前只有它能和CMS收集器(Concurrent Mark Sweep)配合工作。
Serial收集器(老年代是Serial Old)
Parallel收集器(parallel Scavenge, parallel Old)
iParallel收集器CMS收集器
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器,作用于老年代,采用的是标记-清除算法。
CMS收集器工作的整个流程分为以下4个步骤:
- 初始标记(CMS initial mark):仅仅只是标记一下GC Roots能直接关联到的对象,速度很快,需要“Stop The World”。
- 并发标记(CMS concurrent mark):进行GC Roots Tracing的过程,在整个过程中耗时最长。
- 重新标记(CMS remark):为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短。此阶段也需要“Stop The World”。
-
并发清除(CMS concurrent sweep)
cms
优点:
- 并发收集
- 低停顿
缺点: - 因为是和用户工作线程并发执行的,所以会影响用户线程的CPU使用。
- 无法处理浮动垃圾
由于CMS并发清理阶段用户线程还在运行着,伴随程序运行自然就还会有新的垃圾不断产生。这一部分垃圾出现在标记过程之后,CMS无法再当次收集中处理掉它们,只好留待下一次GC时再清理掉。这一部分垃圾就被称为“浮动垃圾”。也是由于在垃圾收集阶段用户线程还需要运行,那也就还需要预留有足够的内存空间给用户线程使用,因此CMS收集器不能像其他收集器那样等到老年代几乎完全被填满了再进行收集,需要预留一部分空间提供并发收集时的程序运作使用。
*标记-清除算法导致的空间碎片
空间碎片过多时,将会给大对象分配带来很大麻烦,往往出现老年代空间剩余,但无法找到足够大连续空间来分配当前对象。这时候CMS会退化为Serial Old。
G1收集器
G1和其他GC算法最大的区别是弱化分代概念,引入分区思想
cms
G1 GC切分堆内存为多个区间(Region),从而避免很多GC操作在整个Java堆或者整个年轻代进行。有的分区内垃圾对象特别多,有的分区内垃圾对象很少,G1会优先回收垃圾对象特别多的分区,这样可以花费较少的时间来回收这些分区的垃圾,这也就是G1名字的由来,即首先收集垃圾最多的分区。
G1的垃圾收集周期主要有4种类型:年轻代收集周期、多级并发标记周期、混合收集周期和full GC(转移失败的安全保护机制)
年轻代收集(YGC)
应用刚启动,慢慢流量进来,开始生成对象。G1会选一个分区并指定他为eden分区,当这块分区用满了之后,G1会选一个新的分区作为eden分区,这个操作会一直进行下去直到达到eden分区上限,也就是说eden分区已经被占满,那么会触发一次年轻代收集。
年轻代收集首先做的就是迁移存活对象,它使用单eden,双survivor进行复制算法,它将存活的对象从eden分区转移到survivor分区,survivor分区内的某些对象达到了任期阈值之后,会晋升到老年代分区中。原有的年轻代分区会被整个回收掉。
网友评论