垃圾收集器

垃圾收集器

在java虚拟机中,有7个垃圾收集器,3个作用于年轻代,3个作用于老年代,还有G1是可以既作用于年轻代,也可以作用于老年代。

图中连线的表示可以组合使用。

Serial

  • 新生代收集器,可以和Serial Old,CMS组合使用;
  • 单线程独占式回收,会产生Stop The World现象;
  • 采用复制算法
  • client模式年轻代默认算法
  • GC日志关键字:DefNew(Default New Generation)

ParNew

  • 新生代收集器,可以和Serial Old, CMS组合使用;
  • 多线程独占式回收,会产生Stop The World现象;
  • 采用复制算法
  • server模式年轻代默认算法
  • 使用-XX:ParallelGCthreads参数来限制垃圾回收的线程数
  • GC日志关键字:ParNew(Parallel New Generation)

Paralle Scavenge

  • 新生代收集器,可以和Serial Old、ParallelOld组合使用
  • 多线程独占式回收,会产生Stop The World现象;
  • 采用复制算法
  • 该收集器非常注重系统的吞吐量,提供了以下参数来调节系统的吞吐量
    • -XX:MaxGCPauseMillis:设置最大垃圾收集停顿时间,单位为毫秒。系统会根据最大垃圾收集停顿时间来调节虚拟机的java堆大小,一个小的堆回收时间更小,但回收次数会增加,导致系统的吞吐量减小。
    • -XX:GCTimeRatio:设置吞吐量的大小(即垃圾回收时间占总时间的比率)设置越小,系统就会根据值设置一个更大的堆,减少垃圾回收的次数,增大吞吐量,但是单次垃圾回收时间会边长。
    • -XX:UseAdaptiveSizePolicy:参数开关,启动后系统动态自适应调节各参数,如-Xmn、-XX:SurvivorRatio等参数,寻找到堆大小,吞吐量和停顿时间之间平衡点。
  • GC日志关键字:PSYoungGen

Serial Old

  • 老年代收集器,可以和所有的年轻代收集器组合使用
  • 采用标记压缩算法
  • 采用单线程独占式算法,会产生Stop The World现象;
  • GC日志关键字:Tenured

Parallel Old

  • 老年代收集器,只能和Parallel Scavenge组合使用
  • 采用标记压缩算法
  • 采用多线程独占式算法,会产生Stop The World现象;
  • GC日志关键字:ParOldGen

CMS( Concurrent Mark Sweep )

  • 老年代收集器, 可以和Serial、ParNew组合使用
  • 采用标记清除算法
    • UserCMSCompactAtFullCollection:默认开启,FullGC时进行内存碎片整理,整理时用户进程需停止,即发生Stop The World
    • CMSFullGCsBeforeCompaction:设置执行多少次不压缩的Full GC后,执行一个带压缩的(默认为0,表示每次进入Full GC 时都会进行碎片整理
  • CMS是并发收集的,就是垃圾回收和用户程序同时进行,但某些阶段还是独占式的,这些阶段还是会出现Stop The World现象
    • 初始标记:独占式的,不能和用户程序同时进行,会Stop the world ,这只是标记根对象
    • 并发标记: 进行GC Roots Tracing,时间长,和用户程序同时进行,不发生用户进程停顿
    • 预清理:和用户程序并发执行,为正式清理做准备和检查,预清理还会尝试控制一次停顿的时间。
    • 重新标记:独占式的,不能和用户程序同时进行,会Stop the world 。因为并发标记是和用户程序同时进行的,在标记的时候,还有垃圾对象不断产生,重新标记就是为了标记那部分对象的。
    • 并发清除:清除垃圾对象,是可以和用户进行同时进行的。
    • 并发重置:垃圾回收完成,重新初始化CMS数据结构和数据。
  • -XX:CMSInitiatingOccupancyFraction 指定当内存使用率到达多少时,执行一次CMS回收,因为CMS回收的时候依然会产生垃圾对象,所以不能等内存满了才来回收。

G1回收器

G1回收器时JDK1.7正式使用的全新垃圾回收器,G1回收器使用分代和分区算法。分代算法就是依然区分年轻代和老年代,依然后eden区和survivor区。分区算法就是不要求整个eden区,年轻代或者老年代都连续。

G1的收集过程

  • 新生代GC
  • 并发标记周期
  • 混合收集
  • 如果需要,可能会进行Full GC

G1的新生代GC

一旦eden区被占满,G1的新生代GC就会发生。

上图中eden区被清空,survivor区保留一部分,old区增多。

G1垃圾收集过程:
1,初始标记:stop the world 标记GC Roots,修改TAMS指针的值(TAMS是用来标识在回收过程用户线程新分配的对象地址区间,这些对象不用参与本次GC,因此要调整TAMS指针,防止下一阶段GC会标记到这些对象)
2,并发标记:从GC Roots开始进行可达性分析,扫描整个堆所有垃圾对象,扫描完成还有重新处理SATB记录(SATB是在GC过程中用户线程删除了的对象引用,因此需要处理这些变动的对象引用)
3,最终标记:stop the world,因此并发标记多次是和用户线程一起执行的,因此在处理SATB的过程,用户线程还会删除对象引用,SATB仍然会增加,因此需要stop the world来处理剩下的少量SATB记录。
4,筛选回收:stop the world 对各个Region的回收价值和成本进行排序,根据用户期望的停顿时间来回收。因为用的是复制算法回收,因此需要移动存活对象,因此必须暂停用户线程。

G1的优点:1,使用Region划分内存空间,回收垃圾多的Region,控制回收停顿的时间。
G1的缺点:1,需要记录自己和各个Region之间的对象引用,需要耗费Java堆容量10%至20%的额外内存。

posted on 2020-04-24 15:54  ggsdduzdl  阅读(159)  评论(0编辑  收藏  举报

导航