几个阶段
- 初始标记: 标记 gc roots直接引用的对象 STW
- 并发标记: 对老年代所有对象进行追踪
-
重新标记:第二阶段过程中系统还在运行,可能产生新的垃圾对象,也可能标记的存活对象变成垃圾对象了, 需要 stop the world 重新标记“并发标记”阶段的对象;
STW , 参考 user 服务remark的对象太多 导致系统停顿 - 并发清理:并发清理前面阶段标记好的对象
cms垃圾回收器的问题
-
消耗cpu资源
并发标记和并发清理的过程中垃圾回收线程虽然能和系统线程同时工作,但是会导致有限的cpu资源被垃圾回收线程占用; cms默认启动的回收线程数为 (cpu核数+3)/4 -
Concurrent Mode Failure
cms 并发清理的过程,只会清理之前标记好的垃圾对象,但是并发清理的同时,系统还在运行着,可能有一些对象进入老年代,然后变为垃圾对象,这种垃圾称为 “浮动垃圾”所以,cms为了避免回收期间,有一些垃圾进入老年代,会预留一些空间;-XX:CMSInitiatingOccupancyFaction 设置老年代占用多少比例就触发cms垃圾回收,jdk1.6 默认为92%
如果cms垃圾回收期间,进入老年代的对象大于可用内存空间,就会发生 Concurrent Mode Failure,此时就会降级用 “Serial Old” 垃圾回收期替代 cms,强行进行 stw 的垃圾回收过程,重新标记垃圾 回收后才恢复系统线程
一般线上 -XX:CMSInitiatingOccupancyFaction 的比例不会那么大 55% 65%这样子
-
内存碎片
cms 采用的是 标记-清理 算法, 所以会有内存碎片的问题,容易导致更加频繁的 full gc-XX:UseCMSCompactAtFullCollection 默认打开,full gc之后 stw 整理内存碎片
-XX:CMSFullGCsBeforeCompaction 执行多少次 full gc 之后进行一次内存碎片整理,默认为0 ,表示每次full gc 之后都会进行一次整理
网友评论