`

JVM调优

    博客分类:
  • JVM
 
阅读更多

在目前的公司,用到的CMS挺多的,以下做一个简单总结:

1、年轻代、年老代没有设置比例,且没有设置大小时,默认是年轻代:年老代=1:2。

2、根据GC信息,就可以看出需要调优的地方,常用jmap打印相关信息。

3、对象进入老年代的条件,要么是通过YGC若干次,达到一定岁数(默认15),则进入。要么survivor空间不足,直接从eden进入老年代(有些大对象在eden的分配也是同理)。另外,也可能是若干相同岁数的对象占用survivor超过一半,则进入老年代。

4、一般想打印出来GC日志,就JVM加上参数:-XX:+PrintGCDateStamps -XX:+PrintGCDetails -Xloggc:/data/gc.log,另外,可通过-XX:+PrintTenuringDistribution打印每次GC时不同对象年龄大小。

5、以CMS收集器为例,full gc的工作过程可以大致分为4个阶段:

初始标记(CMS initial mark)阶段

并发标记(CMS concurrent mark)阶段

重新标记(CMS remark)阶段

并发清除(CMS concurrent sweep)阶段

full gc中,有两个阶段是会STW的,看图,初始标记和重复标记,会暂停用户进程。初始标记阶段的工作是标记GC Roots可以直接关联到的对象,速度很快。并发标记阶段,会从GC Roots 出发,标记处所有可达的对象,这个过程可能会花费相对比较长的时间,但是由于在这个阶段,GC线程和用户线程是可以一起运行的,所以即使标记过程比较耗时,也不会影响到系统的运行。重新标记阶段,是对并发标记期间因用户程序运行而导致标记变动的那部分记录进行修正,重新标记阶段耗时一般比初始标记稍长,但是远小于并发标记阶段。最终,会进行并发清理阶段,和并发标记阶段类似,并发清理阶段不会停止系统的运行,所以即使相对耗时,也不会对系统运行产生大的影响。


 标记文章参考

Initial Mark

这是CMS中两次stop-the-world事件中的一次。它有两个目标:一是标记老年代中所有的GC Roots;二是标记被年轻代中活着的对象引用的对象。

Concurrent Mark

这个阶段会遍历整个老年代并且标记所有存活的对象,从“初始化标记”阶段找到的GC Roots开始。并发标记的特点是和应用程序线程同时运行。并不是老年代的所有存活对象都会被标记,因为标记的同时应用程序会改变一些对象的引用等。

Concurrent Preclean

这个阶段又是一个并发阶段,和应用线程并行运行,不会中断他们。前一个阶段在并行运行的时候,一些对象的引用已经发生了变化,当这些引用发生变化的时候,JVM会标记堆的这个区域为Dirty Card(包含被标记但是改变了的对象,被认为"dirty"),这就是 Card Marking。

Concurrent Abortable Preclean

又一个并发阶段不会停止应用程序线程。这个阶段尝试着去承担STW的Final Remark阶段足够多的工作。这个阶段持续的时间依赖好多的因素,由于这个阶段是重复的做相同的事情直到发生aboart的条件(比如:重复的次数、多少量的工作、持续的时间等等)之一才会停止。

Final Remark

这个阶段是CMS中第二个并且是最后一个STW的阶段。该阶段的任务是完成标记整个年老代的所有的存活对象。由于之前的预处理是并发的,它可能跟不上应用程序改变的速度,这个时候,STW是非常需要的来完成这个严酷考验的阶段。

通常CMS尽量运行Final Remark阶段在年轻代是足够干净的时候,目的是消除紧接着的连续的几个STW阶段。

Concurrent Sweep

和应用线程同时进行,不需要STW。这个阶段的目的就是移除那些不用的对象,回收他们占用的空间并且为将来使用。

Concurrent Reset

这个阶段并发执行,重新设置CMS算法内部的数据结构,准备下一个CMS生命周期的使用。

 

 

 

 

  • 大小: 72.2 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics