垃圾收集器
如果说 收集算法 是内存回收的方法论,那么 垃圾收集器 就是内存回收的具体实现。
下面会介绍7种作用于不同分代的收集器,它们之间有些还可以两两搭配使用。重点分析 CMS 和 G1 收集器。
一、Serial 收集器
特点:
- 单线程收集器。只会使用一个CPU或一条收集线程去完成垃圾收集工作。
- 垃圾收集时,必须暂停其他所有的工作线程,直到收集结束。(“Stop The World”:由虚拟机在后台自动发起和完成,用户不可见)
用途:它依然是虚拟机运行在Client模式下的默认新生代收集器。
优点:简单而高效。对于单CPU环境,它没有线程交互的开销,可以获得最高的单线程收集效率。
二、ParNew 收集器
特点:使用多条线程进行垃圾收集。
使用场景:是许多运行在Server模式下的虚拟机中首选的新生代收集器,原因:除了Serial收集器外,目前只有它能与CMS收集器配合工作。
三、Parallel Scavenge 收集器
特点:
- 使用复制算法,新生代收集器,并行的多线程收集器。
- 关注点:达到一个可控制的吞吐量(Throughput)。所谓吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值。而高吞吐量则可以高效率地利用CPU时间,主要适合在后台运算而不需要太多交互的任务。
- GC自适应的调节策略(GC Ergonomics):虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整一些参数以提供最合适的停顿时间或者最大的吞吐量。通过打开 -XX:UseAdaptiveSizePolicy参数实现。
而CMS等收集器的关注点是:尽可能地缩短垃圾收集时用户线程的停顿时间。停顿时间越短,就越适合需要与用户交互的程序。
提供了两个参数用于精确控制吞吐量,分别是:
- 控制最大垃圾收集停顿时间的 -XX:MaxGCPauseMillis 参数。
- 直接设置吞吐量大小的 -XX:GCTimeRatio 参数。
四、Serial Old 收集器
特点:用于老年代,单线程收集器,使用 “标记-整理” 算法。
主要用途:给Client 模式下的虚拟机使用。
在Server模式下,还有两大用途:
- 在JDK 1.5 及之前的版本中,与 Parallel Scavenge 收集器搭配使用。
- 作为CMS 收集器的后备预案,在并发收集发生 Concurrent Mode Failure 时使用。
五、Parallel Old 收集器
特点:用于老年代,多线程,使用 “标记-整理” 算法。JDK 1.6开始提供。
使用场景:注重吞吐量 以及 CPU资源敏感的场合,Parallel Scavenge 加 Parallel Old 收集器组合。
六、CMS收集器(Concurrent Mark Sweep)
特点:是HotSpot虚拟机中第一款真正意义上的并发(Concurrent)收集器,它第一次实现了让垃圾收集线程与用户线程(基本上)同时工作。基于 “标记-清除”算法实现。
关注点:最短回收停顿时间。
使用CMS来收集老年代的时候,新生代只能选择ParNew或者Serial收集器中的一个。
运作过程:
- 初始标记:只是标记一下GC Roots能直接关联到的对象,速度很快。停顿时间短。
- 并发标记:就是进行 GC Roots Tracing的过程。
- 重新标记:为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录。停顿时间长。
- 并发清除
耗时最长的并发标记和并发清除过程,收集器线程都可以与用户线程一起工作,所以,总体上,CMS收集器的内存回收过程是与用户线程一起并发执行的。
优点:并发收集、低停顿。所以也称之为 并发低停顿收集器(Concurrent Low Pause Collector)。
缺点:
- 对CPU资源非常敏感。
- 无法处理浮动垃圾,可能出现“ Concurrent Mode Failure”失败而导致另一次Full GC 的产生。
- 采用“标记-清除”算法实现,收集结束会有大量的空间碎片产生。
七、G1 收集器
G1是一款面向服务端应用的垃圾收集器。
特点:
- 并行与并发:GC时可通过并发方式让Java程序继续执行。
- 分代收集:独立管理整个GC堆,采用不同的方式收集对象。
- 空间整合:整体看是基于“标记-整理”算法,局部(两个Region之间)看是“复制算法”实现。不会产生内存空间碎片,收集后能提供规整的可用内存。
- 可预测的停顿:低停顿,建立可预测的停顿时间模型。因为它使用Remembered Set 可以有计划的避免在整个Java堆中进行全区域的垃圾收集。每个Region都有一个与之对应的Remembered Set。
- 不同的内存布局:将整个Java堆划分为多个大小相等的独立区域(Region)。新生代和老年代不再是物理隔离的,而是一部分Region集合(不需要连续)。
- 优先回收价值最大的Region:G1跟踪每个Region里垃圾的价值,后台形成优先列表。
运作过程:
- 初始标记:标记一下GC Roots 能直接关联到的对象,并修改 TAMS 的值,让下一阶段用户程序并发时,能在正确可用的 Region 中创建对象。需要停顿线程,耗时很短。
- 并发标记:从 GC Roots 开始对堆中对象进行可达性分析,找出活的对象。耗时较长,可与用户线程并发执行。
- 最终标记:为了修正在并发标记期间因用户程序继续运作而导致标记产生变动的那一部分标记记录,这段时间对象变化记录在线程Remembered Set Logs里面,并合并到Remembered Set中。需要停顿线程,但可并行执行。
- 筛选回收:对各个 Region 回收价值和成本进行排序,根据用户所期望的GC 停顿时间来制定回收计划。
- 并行(Parallel):是指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。
- 并发(Concurrent):指用户线程与垃圾收集线程同时执行(可能会交替执行),用户线程在继续运行,而垃圾收集线程运行在另一个CPU上。
如有错误,欢迎留言指正 * _ *