7种垃圾收集器
新生代:Serial,ParNew,Parallel Scavenge
老年代:Serial old,Parallel old, CMS; CMS用的标记清除算法。
全域垃圾收集器:G1
垃圾收集器演变史:
Serial、serial old->ParNew->Parallel Scavenge、Parallel old->CMS->G1
jdk1.3之前垃圾收集器有Serial,是单线程高效、新生代的,对应老年代版本Serial old;但是单线程垃圾收集器有个问题STW( JVM在后台自动发起和自动完成的,把用户正常的工作线程全部停掉,即 GC停顿,如何减少业务线程的停顿时间),
因此需要类似Serial多线程版的ParNew(大部分代码类似Serial),虽减少停顿时间但在单核cpu情况下效率低于Serial,因线程抢占CPU开销耗时;因提高性能需要,所以
在多线程的情况下需要提升单位时间内吞吐量(吞吐量=业务代码时间/(业务代码时间+垃圾收集时间)),由此,产生了Parallel Scavenge可直接设置吞吐量大小,对应有
老年代版本Parallel old;由此,发现垃圾收集器主要就两个维度,吞吐量和停顿时间,吞吐量靠硬件叠加即可解决,所以更需关注停顿时间,通过分治的思想和并发概念产生了
CMS(concurrent-mark-sweep)垃圾回收器,将标记步骤分为(初始标记、并发标记、重新标记),在并发标记过程中在卡表中记录增量标记,重新标记时会查询增量标记,有空间碎片问题,由此,诞生G1在某种情况下可以解决空间碎片,比CMS多了筛选回收,只有逻辑region,在某种程度上可以连成片空间整合,jdk1.7出现,因最少要求服务
器内存6G,所以1.8为推荐,1.9才默认;CMS默认启动的垃圾回收线程数是(CPU核数+3)/4
卡表:避免跨代引用扫描整个老年代,而只需在新生代上建立一个全局的数据结果,此后当发生young GC时,只有包含了跨代引用的小块内存里的对象才会被加到GC Roots进行扫描。虽然这种办法需要在对象改变引用关系(如将自己或者某个属性赋值)时维护记录数据的正确性,会增加一些运行时的开销,但比起收集时扫描整个老年代来说仍是划算的。
关于垃圾收集器的使用建议:数据量少于100m建议 Serial系,1秒停顿时间以下G1系,1秒以上parallel系。