JVM6——垃圾收集器

垃圾回收算法一共有7个,G1属于横跨年轻代和年老代的算法(整堆收集器)。JVM会从年轻代和年老代各选出一个算法进行组合,”连线“表示哪些算法可以组合使用。
JVM6——垃圾收集器

二、各个垃圾收集器说明
1、Serial(年轻代/新生代)年轻代收集器,可以和Serial Old、CMS组合使用

  • 采用复制算法
  • 使用单线程进行垃圾回收,必须暂停其他所有的工作线程,直到它收集结束。回收时会导致Stop The World,即暂停所有用户进程。(”STOP The World“这项工作是由虚拟机在后台自动发起和自动完成的,在用户不可见的情况下把用户正常工作的线程全部停掉。即GC停顿)
  • client模式下的默认新生代收集器
  • GC日志关键字:DefNew(Default New Generation)
  • 优点:简单高效,不存在线程交互开销。

2、ParNew(年轻代/新生代)年轻代收集器,可以和Serial Old、CMS组合使用

  • 采用复制算法
  • 使用多线程进行垃圾回收,回收时会导致Stop The World,其它策略和Serial一样。相当于多线程版的serial
  • server模式下新生代默认算法
    使用-XX:ParallelGCthreads参数来限制垃圾回收的线程数,默认收集线程和cpu数量相等。
  • GC日志关键字:ParNew(Parallel New Generation)

3、Paralle Scavenge(年轻代/新生代)也叫吞吐量收集器,年轻代收集器,可以和Serial Old、Parallel组合使用,不能和CMS组合使用

  • 采用复制算法
  • 使用并行的多线程进行垃圾回收,回收时会导致Stop The World
    关注系统
  • 达到一个可控制的吞吐量。吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间);高吞吐量即减少垃圾收集时间,让用户代码获得更长的运行时间;

-XX:MaxGCPauseMillis:设置大于0的毫秒数,收集器尽可能在该时间内完成垃圾回收
-XX:GCTimeRatio:大于0小于100的整数,即垃圾回收时间占总时间的比率,设置越小则希望垃圾回收所占时间越小,CPU能花更多的时间进行系统操作,提高吞吐量
-XX:UseAdaptiveSizePolicy:参数开关,启动后系统动态自适应调节各参数,如-Xmn、-XX:SurvivorRatio等参数,这是和ParNew收集器重要的区别
GC日志关键字:PSYoungGen

4、Serial Old(老年代)可以和所有的年轻代收集器组合使用(Serial收集器的年老代版本)

  • 采用 ”标记-整理“算法,会对垃圾回收导致的内存碎片进行整理
  • 使用单线程进行垃圾回收,回收时会导致Stop The World,用户进程停止
    GC日志关键字:Tenured

5、Parallel Old(老年代)只能和Parallel Scavenge组合使用(Parallel Scavenge收集器的年老代版本)
采用 ”标记-整理“算法,会对垃圾回收导致的内存碎片进行整理
关注吞吐量的系统可以将Parallel Scavenge+Parallel Old组合使用
GC日志关键字:ParOldGen

6、CMS(Concurrent Mark Sweep)!

  • 并发标记整理收集器,或并发低停顿收集器,或低延迟收集器
    目标:获取最短回收停顿时间。
    老年代收集器,可以和Serial、ParNew组合使用
  • 采用 ”标记-清除“算法,可以通过设置参数在垃圾回收时处理内存碎片。
    1)UserCMSCompactAtFullCollection:默认开启,FullGC时进行内存碎片整理,整理时用户进程需停止,即发生Stop The World
    2)CMSFullGCsBeforeCompaction:设置执行多少次不压缩的Full GC后,执行一个带压缩的(默认为0,表示每次进入Full GC时都进行碎片整理)
  • CMS是并发算法,表示垃圾回收和用户进行同时进行,但是不是所有阶段都同时进行,在初始标记、重新标记阶段还是需要Stop the World。
    适合于对响应时间要求高的系统
  • GC日志关键字:CMS-initial-mark、CMS-concurrent-mark-start、CMS-concurrent-mark、CMS-concurrent-preclean-start、CMS-concurrent-preclean、CMS-concurrent-sweep、CMS-concurrent-reset等等

CMS垃圾回收分四个阶段
1、初始标记(CMS Initial mark) 需 Stop the World ,仅仅标记一下GC Roots能直接关联到的对象,速度快。
2、并发标记(CMS concurrent mark) 进行GC Roots Tracing ,时间长,不发生用户进程停顿
3、重新标记(CMS remark) 需Stop the World, 修正并发标记期间因用户程序继续运行导致标记变动的那一部分对象的标记记录,停顿时间较长,但远比并发标记时间短
4、并发清除(CMS concurrent sweep) 回收所有垃圾对象,时间长,不发生用户进程停顿
CMS收集器的内存回收过程与用户线程一起并发执行

缺点:
1)对CPU资源非常敏感 ,虽然不会暂停用户线程,但因为占用一部分CPU资源,还是会导致应用程序变慢,总吞吐量降低。
2)CMS收集器无法处理浮动垃圾,(指在并发清除时,用户线程新产生的垃圾),只能等到下次GC时回收 。这使得并发清除时需要预留一定的内存空间,不能像其他收集器在老年代几乎填满再进行收集;即占用更大的堆空间。
3)基于“标记-清除”算法,清除后不进行压缩操作;所以会产生大量碎片

7、G1 Garbage First

  • 并行与并发: 可以并行来缩短"Stop The World"停顿时间; 也可以并发让垃圾收集与用户程序同时进行;
  • 分代收集:能独立管理整个GC堆(新生代和老年代),而不需要与其他收集器搭配;
  • 整体看,基于“标记-整理”算法。局部看(两个region间),基于复制算法可预测的停顿,低停顿的同时实现高吞吐量。可以明确指定M毫秒时间片内,垃圾收集消耗的时间不超过N毫秒;
  • 空间整合,不产生碎片
    G1将整个堆空间划分为多个大小固定的独立区域 region,并跟踪这些区域里的垃圾堆积程度,在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大、垃圾最多的区域Region。

参考:
http://blog.****.net/renfufei/article/details/41897113
http://blog.****.net/woshiqjs/article/details/7290513

分为四个步骤:
1.初始标记: 仅标记一下GC Roots能直接关联到的对象, 需要"Stop The World",但速度很快;
2.并发标记:进行GC Roots Tracing的过程;标记出存活对象,但不能保证标记出所有。 耗时较长,但应用程序也在运行;
3.最终标记:修正并发标记期间因用户程序继续运作而导致标记变动的那一部分对象的标记记录;
4.筛选回收:首先排序各个Region的回收价值和成本;然后根据用户期望的GC停顿时间来制定回收计划;最后按计划回收一些价值高的Region中垃圾对象;采用"复制"算法

参考:《深入理解Java虚拟机:JVM高级特性与最佳实践》