cms垃圾回收

来源:互联网 发布:淘宝店铺怎么装修好看 编辑:程序博客网 时间:2024/05/24 00:46
以下讲的是cms标记清除垃圾回收算法。
http://www.w2bc.com/article/258496

https://github.com/pzxwhc/MineKnowContainer/issues/89

一.目的
大量存活对象,如果使用标记复制,会有大量的对象需要移动,性能会比较差。
这时采用标记清除会比较好。
但随之带来的问题是会产生碎片,因此在实际生产中,需要设置:UseCMSCompactAtFullCollection参数,表示在cms结束后进行一次压缩操作。碎片问题会导致明明老年代有很多空间,但对于晋升到老年代的对象分配不到空间从而导致。

二.适用场景
对象生命周期相对较长。

三.基本流程
1.初始标记
从gc roots开始找,这里的gc roots包括线程栈,静态方法区(静态变量)等。
这步主要是找出有效的root根对象。
应用暂停。

2.并发标记
从得到的root根对象集合,找出所有可到达的对象集合。
应用可以执行。

3.重新标记
解决应用程序产生新的对象,这个对象不能当做垃圾处理。缺少这步,新产生的对象会被当做垃圾处理从而导致结果不正确。
应用暂停。

4.并发清除
清除所有不可到达对象。
浮动垃圾无法在此次清除掉。

四.存在的坑
1.full gc过多
引起原因:
1.1担保失败过多,内存碎片过多

1.2.是否存在sytem.gc,因为这个会引起full gc.
2017-08-06T14:20:55.919-0800: 0.146: [Full GC (System.gc()) [PSYoungGen: 496K->0K(9216K)] [ParOldGen: 40968K->41285K(51712K)] 41464K->41285K(60928K), [Metaspace: 2679K->2679K(1056768K)], 0.0575959 secs] [Times: user=0.37 sys=0.02, real=0.06 secs]
1.3.当需要加载新类时,如果永久代空间不足,则会触发fullGC
CMS回收时默认不会对永久代回收,通过:-XX:+CMSClassUnloadingEnabled设置进行回收
2.cms频率过多
老年代过小,是否存在太多大对象,是否晋升年龄很小(默认15,-XX:MaxTenuringThreshold
是否存在内存泄露,现象就是年轻代不断minor gc,然后回收不掉,晋升到老年代。


五.如何优化

优化根据应用类型,一般应用很难区分开短对象多还是长期存活对象多。
像mq消费型的应用,就适合年轻代设置大点,因为对象都是短期对象,消费完就释放。

默认老年代与新生代比例是:0.75:0.25。mac比例为:0.66

需要根据业务类型进行压测。
看瓶颈出现在哪里。
而可能出现的瓶颈有:
cpu,io,内存,jvm垃圾回收,死锁,数据库等。

需要根据具体问题来进行相应的优化。

可能出现的情况:

1.晋升失败
concurrent model failer
在cms时,由于应用程序还在运行,因此可能会有新对象进入老年代,而这时发现老年代无足够空间时会发生晋升失败,从而导致cms gc退化成full gc。
如何优化:
a.可以调低cms触发的限值,通过参数:XX:CMSInitiatingOccupancyFractionXX:UseCMSInitiatingOccupancyOnly
这样可以使cms在垃圾回收,能够有足够的老年代空间应对新进入的对象。默认为:68。
2.提升cms gc速度
jvm不能太大,太大本身就需要更多的垃圾回收时间。4g堆比较合适。多实例部署。
在cms gc前可以尝试进行minor gc,对新生代回收。这么做原因是老年代很多对象会引用到新生代对象,这样可以减少标记(初始与并发标记)的时间。参数:CMSScavengeBeforeRemark。


原创粉丝点击