垃圾收集器

来源:互联网 发布:ubuntu ctrl alt t 编辑:程序博客网 时间:2024/05/22 00:07
HotSpot虚拟机中的垃圾收集器

Serial收集器

  • 新生代收集器
  • Serial收集器是一个单线程的收集器,即只会使用一个CPU或一条收集线程去完成来收集工作,更重要的是在进行收集时,必须暂停其他所有的工作线程,直到收集结束。
  • serial收集器的工作过程

  • Serial收集器对于运行在Client模式下的虚拟机来说是一个很好的选择。

ParNew收集器

  • 新生代收集器
  • ParNew收集器是Serial收集器的多线程版本。
  • ParNew收集器的运行过程

  • ParNew收集器是运行在Server模式下新生代收集器的首选。
  • 默认开启的收集线程数与CPU的数量相同,可以使用-XX:ParallelGCThreads参数来限制垃圾收集的线程数。
小知识:在讨论垃圾收集器的上下文语境中,并发和并行的理解如下:
并行(Parallel):指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。
并发(Concurrent):指用户线程与垃圾收集线程同时执行(但不一定是并行,可能会交替执行),用户程序在继续运行,而垃圾收集程序运行于另一个CPU上。

Parallel  Scavenge收集器

  • 新生代收集器
  • 并行的多线程收集器
  • Parallel  Scanvege收集器的目标是达到一个可控制的吞吐量(Throughput),所谓吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值,
    即吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间),高吞吐量则可以高效地利用CPU时间,尽快完成程序的运算任务,主要适合在后台运算而不需要太多交互的任务。
  • 提供的两个参数来精确控制吞吐量:控制最大垃圾收集停顿时间的-XX:MaxGCPauseMillis参数      直接设置吞吐量大小的-XX:GCTimeRatio参数   
    GC自适应调节策略(GC  Ergonomics):-XX  +UseAdaptiveSizePolicy
  • Parallel Scavenge收集器架构中本身有PS  MarkSweep收集器来进行老年代收集,并非直接使用了Serial Old收集器,但是PS MarkSweep收集器与Serial Old收集器的实现非常接近。

Serial  Old收集器

  • 老年收集器
  • 单线程收集器,使用“标记-整理”算法。
  • 主要使用在Client模式下的虚拟机中。在Server模式下,有两大用途:第一在JDK1.5以及之前的版本中与Parallel  Scavenge收集器搭配使用,第二作为CMS收集器的后备预案,在并发收集发生Concurrent  Mode Failure时使用。
  • Serial  Old收集器的运行过程:

Parallel  Old收集器

  • Parallel Old是Parallel Scavenge收集器的老年代版本
  • 使用多线程和“标记-整理”算法
  • 在注重吞吐量以及CPU资源敏感的场合,可以优先考虑Parallel Scavenge+Parallel Old收集器。
  • Parallel Old 工作工程如下:

CMS(Concurrent Mark Sweep)收集器

  • 年老代收集器
  • 以获取最短回收停顿时间为目标的收集器,基于:标记--清除算法实现
  • CMS收集器的执行过程包括四个步骤:
    第一:初始标记(CMS   initial  mark)
     执行时需要停止所有线程,标记GC Roots能直接关联到的对象,速度很快。
    第二:并发标记(CMS   concurrent  mark)
    并发标记阶段就是进行GC  RootsTracing过程,可以与用户线程一起工作。
    第三:重新标记(CMS remark)
    执行时需要停止所有线程,为了修正并发标记期间因为用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但是比并发标记的时间段。
    第四:并发清除(CMS  concurrent  sweep)
    可以与用户线程一起工作
  • CMS的执行过程

  • CMS默认启动的回收线程数是(CPU+3)/4,即当CPU在4个以上时,并发回收时垃圾收集线程不少于25%的CPU资源,并且随着CPU数量的增加而下降。
  • CMS收集器无法处理浮动垃圾(Floating Garbage),如果CMS运行期间预留的内存无法满足程序需要,就会出现“Concurrent  Mode Failure”失败,这时虚拟机将启动后备预案:临时启用Serial Old收集器来重新进行老年代的垃圾收集。由于CMS并发清理阶段用户线程还在运行着,伴随程序运行自然就还会有新的垃圾不断产生,这一部分垃圾出现在标记过程之后,CMS无法在当次收集中处理掉它们,只好留待下一次GC时再清理掉。这一部分垃圾就是浮动垃圾。由于在垃圾收集阶段用户线程还需要运行,就需要预留有足够的内存空间给用户线程使用,因此CMS收集器不能像其他收集器那样等到老年代几乎完全被填满了再进行收集,需要预留一部分空间提供并发收集时的程序运作使用。
  • -XX:CMSInitiatingOccupancyFraction可以通过设置触发百分比(即老年代内存的使用的百分比来触发),以便降低内存回收次数从而获得更好的性能。如果CMS运行期间预留的内存无法满足程序需要,就会出现“Concurrent  Mode Failure”失败。
  • -XX:+UseCMSCompactAtFullCollection开关参数(默认是开启的),用于CMS收集器顶不住要进行FullGC时开启内存碎片的合并整理过程,内存整理的过程无法并发的,空间碎片问题没了,但是停顿时间不得不边长。
    -XX:CMSFullGCsBeforeCompaction,这个参数是用于设置执行多少次不压缩的Full GC后,跟着来一次带压缩的(默认值为0,表示每次进入Full GC时都进行碎片整理)。

G1(Garbage-First)收集器

  • G1是一款面要服务端应用的垃圾收集器。
  • G1能充分利用多CPU、多核环境下的硬件优势,使用多个CPU(CPU或者CPU核心)来缩短Stop-The-World停顿时间,部分其他收集器原本需要停顿Java线程执行的GC动作,G1收集器仍然可以通过并发的方式让Java程序继续执行。
  • 分代收集
    与其他收集器一样,分代概念在G1中依然得以保留。虽然G1可以不需要其他收集器配合就能独立管理整个GC堆,但它能够采用不同的方式处理新创建的对象和已经存活了一段时间、熬过多次GC的就对象以获取更好的收集效果。
  • 空间整合
    G1从整体来看是基于“标记-整理”算法实现的收集器,从局部(两个Region)上来看是基于“复制”算法实现的,这两种算法在G1运作期间都不会产生内存空间碎片,收集后能提供规整的可用内存。
  • 可预测的停顿
    G1追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒,这几乎已经是实时Java(RTSJ)的垃圾收集器的特征了。G1收集器之所以能建立可预测的停顿时间模型,是因为它可以有计划地避免在整个Java堆中进行全区域的垃圾收集,G1跟踪各个Region里面的垃圾堆积的价值大小(回收所获得的空间大小以及回收所需时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的Region即Garbage-First的来由,使用Region划分内存空间以及有优先级的区域回收方式,保证了G1收集器在有限的时间内可以获取尽可能高的收集效率。
  • 内存布局
    将整个Java堆划分为多个大小相等的独立区域(Region),虽然保留有新生代和年老代的概念,但新生代和年老代不再是物理隔离的了,都是一部分Region(不需要连续)的集合。
  • G1运作的过程
    第一:初始标记(Initial  Marking)
    只是标记一下GC Roots能直接关联到的对象,并且修改TAMS(Next  Top at Mark Start)的值,让下一阶段用户程序并发运行时,能在正确可用的Region中创建新对象,这阶段需要停顿线程,但耗时很短。
    第二:并发标记(Concurrent Marking)
    从GC Root开始对堆中对象进行可达性分析,找出存活的对象,这阶段耗时较长,但可与用户程序并发执行
    第三:最终标记(Final Marking)
    为了修正在并发标记期间因用户程序继续运行而导致标记产生变动的哪一部分标记记录,虚拟机将这段时间对象变化记录在线程Remembered Set  Logs里面,最终标记阶段需要把Remembered  Set  Logs的数据合并到Remembered  Set中,这阶段需要停顿线程,但是可并行执行。
    第四:筛选回收(Live Data Counting and  Evacuation)
    最后在筛选回收阶段首先对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划。


1 0
原创粉丝点击