CMS与G1-接上一篇

垃圾回收-浅谈JVM垃圾算法
首先要知道 Stop the world的含义:不管选择哪种GC算法,stop-the-world都是不可避免的。Stop-the-world意味着从应用中停下来并进入到GC执行过程中去。一旦Stop-the-world发生,除了GC所需的线程外,其他线程都将停止工作,中断了的线程直到GC任务结束才继续它们的任务。GC调优通常就是为了改善stop-the-world的时间

  1. CMS
    CMS收集器是一种以获取最短回收停顿时间为目标的收集器,CMS收集器是基于“”标记–清除”(Mark-Sweep)算法实现的,整个过程分为四个步骤

        1. 初始标记 (Stop the World事件 CPU停顿, 很短) 初始标记仅标记一下GC Roots能直接关联到的对象,速度很快;
    
        2. 并发标记 (收集垃圾跟用户线程一起执行) 初始标记和重新标记任然需要“stop the world”,并发标记过程就是进行GC Roots Tracing的过程;
    
        3. 重新标记 (Stop the World事件 CPU停顿,比初始标记稍微长,远比并发标记短)修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记时间短
    
        4. 并发清理 -清除算法;
    

整个过程中耗时最长的并发标记和并发清除过程收集器线程都可以与用户线程一起工作,所以,从总体上来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。

初始标记:仅仅是标记一下GC roots 能直接关联的对象,速度很快 (何为GC roots :

在Java语言中,可作为GC Roots的对象包括4种情况:

a) 虚拟机栈中引用的对象(栈帧中的本地变量表);

b) 方法区中类静态属性引用的对象;

c) 方法区中常量引用的对象;

d) 本地方法栈中JNI(Native方法)引用的对象。
  
优点: 并发收集, 低停顿
缺点: 因为第四步是GC线程与用户线程并行执行, 所以产生的垃圾无法及时回收. 也就是浮动垃圾.
因为是标记-清除算法, 所以会产生对碎片, 那么对于大对象的产生有可能分配不到有效空间, 导致提前FULL GC

2. G1 标记整理

G1虽然也把内存分成了这三大类,但是在G1里面这三大类不是泾渭分明的三大块内存,G1把内存划分成很多小块, 每个小块会被标记为E/S/O中的一个,可以前面一个是Eden后面一个就变成Survivor了。
在这里插入图片描述
由于把三块内存变成了几百块内存,内存块的粒度变小了,从而可以垃圾回收工作更彻底的并行化.

G1的另一个显著特点他能够让用户设置应用的暂停时间,为什么G1能做到这一点呢?也许你已经注意到了,G1回收的第4步,它是“选择一些内存块”,而不是整代内存来回收,这是G1跟其它GC非常不同的一点,其它GC每次回收都会回收整个Generation的内存(Eden, Old), 而回收内存所需的时间就取决于内存的大小,以及实际垃圾的多少,所以垃圾回收时间是不可控的;而G1每次并不会回收整代内存,到底回收多少内存就看用户配置的暂停时间,配置的时间短就少回收点,配置的时间长就多回收点,伸缩自如。

回收的四个步骤:

	1. 初始标记(stop the world事件 CPU停顿只处理垃圾);
   
   	2. 并发标记(与用户线程并发执行);
   
   	3. 最终标记(stop the world事件 ,CPU停顿处理垃圾);
   
   	4. 筛选回收(stop the world事件 根据用户期望的GC停顿时间回收)(注意:CMS 在这一步不需要stop the world), Garbage First的原则,选择一些内存块进行回收;
  1. 我们会发现以上的四个步骤, 第四步是与CMS不同的, CMS是不STW的, G1的第四步是要STW的, 可以解决CMS 的浮动垃圾问题, 而且时间暂停会靠近设置的暂停值, 不回耽误很长时间.
  2. 可预测的停顿 相比于CMS 我们可以预测出停顿的时间
  3. G1 收集器的特性需要分多个小块内存 所以一般来说 需要的整体的JVM内存 也是大的

猜你喜欢

转载自blog.csdn.net/weixin_45657738/article/details/111866658