设为首页 加入收藏

TOP

图解 CMS 垃圾回收机制,你值得拥有(二)
2018-01-22 17:24:42 】 浏览:1543
Tags:图解 CMS 垃圾 回收 机制 值得 拥有
新标记,这里的Dirty Card大部分已经在clean阶段处理过

在第一步骤中,需要遍历新生代的全部对象,如果新生代的使用率很高,需要遍历处理的对象也很多,这对于这个阶段的总耗时来说,是个灾难(因为可能大量的对象是暂时存活的,而且这些对象也可能引用大量的老年代对象,造成很多应该回收的老年代对象而没有被回收,遍历递归的次数也增加不少),如果在AbortablePreclean阶段中能够恰好的发生一次YGC,这样就可以避免扫描无效的对象。

如果在AbortablePreclean阶段没来得及执行一次YGC,怎么办?

CMS算法中提供了一个参数:CMSScavengeBeforeRemark,默认并没有开启,如果开启该参数,在执行该阶段之前,会强制触发一次YGC,可以减少新生代对象的遍历时间,回收的也更彻底一点。

不过,这种参数有利有弊,利是降低了Remark阶段的停顿时间,弊的是在新生代对象很少的情况下也多了一次YGC,最可怜的是在AbortablePreclean阶段已经发生了一次YGC,然后在该阶段又傻傻的触发一次。

所以利弊需要把握。

主动Old GC

这个主动Old GC的过程,触发条件比较苛刻:

  1. YGC过程发生Promotion Failed,进而对老年代进行回收
  2. 比如执行了System.gc(),前提是没有参数ExplicitGCInvokesConcurrent
  3. 其它情况…

如果触发了主动Old GC,这时周期性Old GC正在执行,那么会夺过周期性Old GC的执行权(同一个时刻只能有一种在Old GC在运行),并记录 concurrent mode failure 或者 concurrent mode interrupted。

主动GC开始时,需要判断本次GC是否要对老年代的空间进行Compact(因为长时间的周期性GC会造成大量的碎片空间),判断逻辑实现如下:

*should_compact =
    UseCMSCompactAtFullCollection &&
    ((_full_gcs_since_conc_gc >= CMSFullGCsBeforeCompaction) ||
     GCCause::is_user_requested_gc(gch->gc_cause()) ||
     gch->incremental_collection_will_fail(true /* consult_young */));

在三种情况下会进行压缩:

  1. 其中参数UseCMSCompactAtFullCollection(默认true)和 CMSFullGCsBeforeCompaction(默认0),所以默认每次的主动GC都会对老年代的内存空间进行压缩,就是把对象移动到内存的最左边。
  2. 当然了,比如执行了System.gc(),前提是没有参数ExplicitGCInvokesConcurrent,也会进行压缩。
  3. 如果新生代的晋升担保会失败。

带压缩动作的算法,称为MSC,标记-清理-压缩,采用单线程,全暂停的方式进行垃圾收集,暂停时间很长很长…

那不带压缩动作的算法是什么样的呢?

不带压缩动作的执行逻辑叫Foreground Collect,整个过程相对周期性Old GC来说,少了Precleaning和AbortablePreclean两个阶段,其它过程都差不多。

如果执行System.gc(),而且添加了参数ExplicitGCInvokesConcurrent,这时并不属于主动GC,它会推进周期性Old GC的进行,比如刚刚执行过一次,并不会等2s后检查条件,而是立马启动周期性Old GC。

首页 上一页 1 2 下一页 尾页 2/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇G1 垃圾收集器之对象分配过程 下一篇2018 年 Java 平台发布计划之新特..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目