单线程回收器
单线程回收器是指只开启一个线程进行垃圾回收的操作,进行垃圾回收时,暂停用户工作线程。在单CPU环境下,单线程回收器没有线程切换的开销,专心垃圾收集,更加简单高效。
1、Serial
新生代使用,采用复制算法。
2、Serial Old
老年代使用,采用标记整理算法。
Serial一般与Serial Old搭配使用
多线程回收器
顾名思义,多线程回收器通过多线程来进行垃圾回收。进行垃圾回收时,暂停用户工作线程。
1、ParNew
Serial的多线程版本,新生代使用,采用复制算法。
2、Parallel Scavenge
新生代使用,采用复制算法。该算法关注吞吐量,如果设置了吞吐量的值,会动态调整新生代、eden区和survivor区的大小,使其尽可能达到设置的吞吐量。
-XX:MaxGCPauseMillis:设置最大停顿时间;
-XX:GCTimeRatio:设置吞吐量大小n,取值范围,公式1/(1+n)结果为垃圾回收时间与总时间(垃圾回收+用户线程)的比值。
3、Parallel Old
老年代使用,采用标记整理算法。
4、CMS
老年代使用,采用标记清除算法。该算法关注垃圾回收过程中暂停所有工作线程的时间(越短越好)。进行垃圾清理时,用户工作线程同时运行。
初始标记:暂停用户工作线程,标记GC Roots对象和GC Roots直接引用的对象,理论上来说需要标记对象比较少,速度很快;
并发标记:向下搜索,标记GC Roots直接引用对象引用的对象,这个过程可以与用户线程并发执行,耗时较长,但是用户无感知;
重新标记:并发标记过程中存在用户线程的执行,会产生新的GC Roots对象或GC Roots引用对象,需要将它们也标记起来,速度较快;
并发清理:清除没有标记的对象,回收内存空间;
重置:垃圾回收器内部数据结构重置。
注意:并发过程中产生的浮动垃圾需要再下一次垃圾回收中才能被清理,当CMS因为浮动垃圾过多导致出现异常时,JDK会使用默认的Serial Old垃圾回收器执行一次Full GC。
G1
新生代/老年代使用,内存上没有明确的新生代、老年代界限,采用标记整理算法。进行垃圾回收时,用户工作线程可同时运行。
G1分区:
存在一个巨型对象(Humongous),存放占内存较大的对象。
过程与CMS有相似之处,但是存在整理过程,不会产生内存碎片。
图解:
算法的搭配
一般来说,按照下面所示搭配使用
如果有写的不对的地方,请大家多多批评指正,非常感谢!