垃圾回收算法和垃圾收集器
垃圾回收算法
- 复制
- 标记清除
- 标记整理
- 分代收集算法
垃圾回收器
- 串行垃圾回收器(Serial)
- 它为单线程环境设计且只使用一个线程进行垃圾回收,会暂停所有的用户线程,所以不适合服务环境
- 并行垃圾回收器(Parallel)
- 多个垃圾收集线程并行工作,此时用户线程是暂停的,用于科学计算、大数据处理等弱交互场景
- 并发垃圾回收器(CMS)
- 用户线程和垃圾收集线程同时执行(不一定是并行,可能是交替执行),不需要停顿用户线程,互联网公司多用它,适用对相应时间有要求的场景
- G1 垃圾回收器
- G1 垃圾回收器将堆内存分割成不同的区域然后并发的对其进行垃圾回收
Java 的 GC 回收的类型
- UseSerialGC,UseSerialOldGC,UseParallelGC,UseParallelOldGC,UseParNewGC,UseConcMarkSweepGC,UseG1GC
- 新生代
- 串行 GC (Serial/ Serital Copying)
- 并行 GC (ParNew)
- 并行回收 GC (Parallel/ Parallel Scanvenge)
- 老年代
- 串行 GC (Serial Old/ Serial MSC)
- 并行 GC (Parallel Old/ Parallel MSC)
- 并发标记清除 GC (CMS)
- 是一种以获取最短回收停顿时间为目标的收集器,适合应用在互联网或者 B/S 系统的服务器上,这类应用尤其重视服务器的响应速度,希望系统停顿时间最短
- CMS 非常适合堆内存大、CPU 核数多的服务器端应用,也是 G1 出现之前大型应用首选收集器
- 并发停顿比较少,并发指的是与用户线程一起执行
- 过程
- 初始标记(initail mark):只是标记一下 GC Roots 能直接关联的对象,速度很快,需要暂停所有的工作线程
- 并发标记(concurrent mark 和用户线程一起):进行 GC Roots 的跟踪过程,和用户线程一起工作,不需要暂停工作线程
- 重新标记(remark):为了修正在并发标记期间,因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,仍然需要暂停所有的工作线程
- 并发清除(concurrent sweep 和用户线程一起):清除 GC 不可达对象,和用户线程一起工作,不需要暂停工作线程,基于标记结果,直接清除。由于耗时最长的并发标记和并发清除过程中,垃圾收集线程和用户线程可以一起并发工作,所以总体来看 CMS 收集器的内存回收和用户线程是一起并发地执行
- 优缺点
- 优点:并发收集停顿低
- 缺点:并发执行对 CPU 资源压力大,采用的标记清除算法会导致大量碎片
- 由于并发进行, CMS 在收集与应用线程会同时增加对堆内存的占用,也就是说,CMS 必须要在老年代堆用尽之前完成垃圾回收,否者 CMS 回收失败,将触发担保机制,串行老年代收集器将会以 STW 的方式进行一次 GC,从而造成较大的停顿时间
- 标记清除算法无法整理空间碎片,老年代空间会随着应用时长被逐渐耗尽,最后将不得不通过担保机制对堆内存进行压缩。CMS 也提供了参数-XX:CMSFullGCsBeForeCompaction (默认0,即每次都进行内存整理) 来指定多少次 CMS 收集之后,进行一次压缩
如何选择垃圾收集器
- 单 CPU 或者小内存,单机程序:-XX:UseSerialGC
- 多 CPU 需要最大吞吐量,如后台计算型应用:-XX:UseParallelGC 或者 -XX:UseParallelOldGC
- 多 CPU 追求低停顿时间,需要快速响应,如互联网应用:-XX:+UseConcMarkSweepGC
附:JVM学习目录