GC 知识点补充——CMS
之前已经讲过了不少有关 GC 的内容,今天准备将之前没有细讲的部分进行补充,首先要提到的就是垃圾收集器。
基础的回收方式有三种:清除
、压缩
、复制
,衍生出来的垃圾收集器有:
Serial 收集器
新生代收集器,使用停止复制算法,使用一个线程进行 GC ,串行,其它工作线程暂停。
使用-XX:+UseSerialGC
开关来控制使用Serial + Serial Old
模式运行进行内存回收(这也是虚拟机在 Client 模式下运行的默认值)。
ParNew 收集器
新生代收集器,使用停止复制算法,Serial 收集器的多线程版,用多个线程进行 GC ,并行,其它工作线程暂停,关注缩短垃圾收集时间。
使用-XX:+UseParNewGC
开关来控制使用ParNew + Serial Old
收集器组合收集内存;使用-XX:ParallelGCThreads
来设置执行内存回收的线程数。
Parallel Scavenge 收集器
新生代收集器,使用停止复制算法,关注 CPU 吞吐量,即运行用户代码的时间/总时间
,比如:JVM 运行 100 分钟,其中运行用户代码 99 分钟,垃 圾收集 1 分钟,则吞吐量是 99% ,这种收集器能最高效率的利用 CPU ,适合运行后台运算(其他关注缩短垃圾收集时间的收集器,如 CMS ,等待时间很少,所以适 合用户交互,提高用户体验)。
使用-XX:+UseParallelGC
开关控制使用Parallel Scavenge + Serial Old
收集器组合回收垃圾(这也是在 Server 模式下的默认值);使用-XX:GCTimeRatio
来设置用户执行时间占总时间的比例,默认 99 ,即 1% 的时间用来进行垃圾回收。使用-XX:MaxGCPauseMillis
设置 GC 的最大停顿时间(这个参数只对 Parallel Scavenge 有效),用开关参数-XX:+UseAdaptiveSizePolicy
可以进行动态控制,如自动调整 Eden / Survivor 比例,老年代对象年龄,新生代大小等,这个参数在 ParNew 下没有。
Serial Old 收集器
老年代收集器,单线程收集器,串行,使用标记-整理
算法,使用单线程进行GC,其它工作线程暂停(注意:在老年代中进行标记-整理
算法清理,也需要暂停其它线程),在JDK1.5之前,Serial Old 收集器与 ParallelScavenge 搭配使用。
整理的方法是 Sweep (清除)和 Compact (压缩),清除是将废弃的对象干掉,只留幸存的对象,压缩是移动对象,将空间填满保证内存分为2块,一块全是对象,一块空闲),
Parallel Old 收集器
老年代收集器,多线程,并行,多线程机制与 Parallel Scavenge 差不错,使用标记-整理
算法,在 Parallel Old 执行时,仍然需要暂停其它工作线程。
Parallel Old 收集器的整理,与 Serial Old 不同,这里的整理是Copy(复制)和Compact(压缩),复制的意思就是将幸存的对象复制到预先准备好的区域,而不是像Sweep(清除)那样清除废弃的对象。
Parallel Old 在多核计算中很有用。 Parallel Old 出现后(JDK 1.6),与 Parallel Scavenge 配合有很好的效果,充分体现 Parallel Scavenge 收集器吞吐量优先的效果。使用-XX:+UseParallelOldGC
开关控制使用Parallel Scavenge + Parallel Old
组合收集器进行收集。
CMS
全称 Concurrent Mark Sweep,老年代收集器,致力于获取最短回收停顿时间(即缩短垃圾回收的时间),使用标记-清除
算法,多线程,优点是并发收集(用户线程可以和 GC 线程同时工作),停顿小。
使用-XX:+UseConcMarkSweepGC
进行ParNew + CMS + Serial Old
进行内存回收,优先使用ParNew + CMS
(原因见后面),当用户线程内存不足时,采用备用方案