美文网首页
垃圾回收:Concurrent Mark and Sweep(C

垃圾回收:Concurrent Mark and Sweep(C

作者: 胖达_4b7e | 来源:发表于2019-01-27 17:08 被阅读0次

    https://downloads.plumbr.io/java%20lang%20OutOfMemoryError%20Handbook%20-%20Plumbr.pdf

    垃圾回收的实现

    事实是,虚拟机一般需要2种GC分别用于清理:新生代和老年期
    我可以指定,如果不指定也会有默认的



    虽然图中有很多, 事实上只用加粗的4种

    • 1.都用Serial
    • 2.都用Parallel
    • 3.Parallel 和 CMS
    • 4.都用G1

    Concurrent Mark and Sweep

    老年代的收集器(和ParNew配合), 并发 标记-清除
    目标是避免老年代收集时的长停顿,
    这靠2个措施:

    • 1.标记以后不压缩. 只用free-lists来管理收回的空间
    • 2.标记-清除的大多数工作 和 应用 同时进行, 这意味着 不是完全停止应用线程, 用多线程来完成收集

    默认用于gc的线程为 (cpu核数+3)/4
    因为和应用并行,不能等满了,应用没内存用了才发起,而是老年代内存占用达到68%(可调)就要发起

    使用示例

    java -XX:+UseConcMarkSweepGC com.mypackages.MyExecutableClass
    

    看 全GC的日志

    2015-05-26T16:23:07.321-0200: 64.425: [GC (CMS Initial Mark) [1 CMS-initial-mark:
    10812086K(11901376K)] 10887844K(12514816K), 0.0001997 secs] [Times: user=0.00 sys=0.00,
    real=0.00 secs]
    
    2015-05-26T16:23:07.321-0200: 64.425: [CMS-concurrent-mark-start]
    2015-05-26T16:23:07.357-0200: 64.460: [CMS-concurrent-mark: 0.035/0.035 secs] [Times:
    user=0.07 sys=0.00, real=0.03 secs]
    
    2015-05-26T16:23:07.357-0200: 64.460: [CMS-concurrent-preclean-start]
    2015-05-26T16:23:07.373-0200: 64.476: [CMS-concurrent-preclean: 0.016/0.016 secs]
    [Times: user=0.02 sys=0.00, real=0.02 secs]
    
    2015-05-26T16:23:07.373-0200: 64.476: [CMS-concurrent-abortable-preclean-start]
    2015-05-26T16:23:08.446-0200: 65.550: [CMS-concurrent-abortable-preclean: 0.167/1.074
    secs] [Times: user=0.20 sys=0.00, real=1.07 secs]
    
    2015-05-26T16:23:08.447-0200: 65.550: [GC (CMS Final Remark) [YG occupancy: 387920 K
    (613440 K)]65.550: [Rescan (parallel) , 0.0085125 secs]65.559: [weak refs processing,
    0.0000243 secs]65.559: [class unloading, 0.0013120 secs]65.560: [scrub symbol table,
    0.0008345 secs]65.561: [scrub string table, 0.0001759 secs][1 CMS-remark:
    10812086K(11901376K)] 11200006K(12514816K), 0.0110730 secs] [Times: user=0.06 sys=0.00,
    real=0.01 secs]
    
    2015-05-26T16:23:08.458-0200: 65.561: [CMS-concurrent-sweep-start]
    2015-05-26T16:23:08.485-0200: 65.588: [CMS-concurrent-sweep: 0.027/0.027 secs] [Times:
    user=0.03 sys=0.00, real=0.03 secs]
    
    2015-05-26T16:23:08.485-0200: 65.589: [CMS-concurrent-reset-start]
    2015-05-26T16:23:08.497-0200: 65.601: [CMS-concurrent-reset: 0.012/0.012 secs] [Times:
    user=0.01 sys=0.00, real=0.01 secs]
    

    和前2个收集器不同, CMS 是分阶段的

    也可能会 并发收集失败 Concurrent Mode Failure, 这是因为老年代空间不足(老是这样就需要调大老年代, 或者调小触发阈值)
    如果失败,就会用最古老最慢的Serial Old 来收集, 这就慢了

    1: Initial Mark 初始标记(STW)

    这是唯二的需要 stop-the-world 的阶段
    这阶段目的是 标记 根对象, 就是GC roots能直接关联到的对象, 很快就能完成


    1.2015-05-26T16:23:07.321-0200 发生的时刻, 64.425 JVM 运行了这时长时发生
    3.4.老年代 现在占的内存 总可用内存
    5.6.堆 现在占的内存. 总可用内存
    7.所用的时间

    2:Concurrent Mark 并发标记

    如名字所说,标记所有对象, 和应用同时进行,应用不用停
    从上一个阶段得到的 根对象 出发, 在老年代标记 所有活着的对象



    3.这个所花的时间值, 没有多大的意义, 因为这段时间是和应用一起的,不止是垃圾回收线程在干活

    3: Concurrent Preclean 并发预清理

    也是和应用同时地进行的阶段

    上一个阶段标记的一些有了变化, 有字段变化的对象被标记为dirty(这叫Card Marking),上一个阶段标记为活的可能有错,实际上死了,但是重要的是 活的没被认为是死的. 这个阶段也为最终标记阶段做准备


    4: Concurrent Abortable Preclean 可中止的并发预清理

    也是不用停应用的, 为了减轻下一个停应用的阶段(最终重标记)的负担
    这个阶段的时间有很多影响因素,因为迭代做很多事,直到遇到停止条件(如:迭代次数,完成的有用工作量,经过的时间等)



    2.cpu时间/时钟时间(真的过去的时间):

    user/real
    用户时间user,就是cpu时间,
    真实时间real,就时钟时间,在现实世界过去的世界

    值得注意的是,user比real小很多,
    这是不正常的,

    一般来说,real会比user少,这是因为工作可多线程并发来干, 比较快.

    这里, user只有0.167,做了一点点工作, 垃圾收集线程们只是等了几乎一秒,没干啥
    因为下一个阶段是STW的, 本阶段会特点等一次小GC,根据历史性能数据 预测下一次小GC的时间, 让下一个阶段和小GC 不连着发现(尽量让下一个阶段开始在2次小GC的中点), 如果连着的话 应用就一次停太久了

    5: Final Remark 最终重新标记(STW)

    停应用. 目标是最终标记老年代 所有 活着的线程
    加上脏对象(并行阶段被改的)
    这个阶段比初始标记的阶段会时间长一点, 但是远比并发标记短

    CMS尽量在新生代空的时候执行这个节点, 为了避免连续 stop-the-world


    4.多线程的重新扫描活着的对象, 当应用停止, 耗时这些秒
    5.子阶段:处理弱引用的时间长和时刻
    6.子阶段:卸载不用的类,用的时长和发生的时刻
    7.子阶段:清朝标志(类级别的元信息)和字符串表(内化的字符串)
    10.耗时

    5个阶段用户,所有老年代活的对象都已经被标记,可以开始清除老年代了

    6: Concurrent Sweep 并发清理

    不停应用
    目的是,移除没用的对象,重新声明他们占的空间以后可以用了


    7: Concurrent Reset. 并发重置

    重置内部数据结构,为下一次轮回准备


    总结

    CMS依靠把很多工作用并发线程(不停应用)们来执行,来避免停顿时间
    缺点是,
    1.标记清除的缺点,就是老年代的碎片

    可以开启每次都碎片整理(STW),还可以设定多少次以后 内存压缩

    2.区分停止时间的预见性,特别是堆大的时候

    还是G1好

    相关文章

      网友评论

          本文标题:垃圾回收:Concurrent Mark and Sweep(C

          本文链接:https://www.haomeiwen.com/subject/wnfwjqtx.html