深入JVM内核(四)垃圾回收器与GC参数
date: 2018-10-18 13:03:17
堆的回顾
很多垃圾回收算法,如CMS,使用的堆内存结构如下:
新手代:一个Eden和两个survivor
老年代:old space
持久带:1.8之前的perm space
元空间:1.8之后的metaspace
注:这些space必须是地址连续的空间
串行(Serial)收集器
- 单线程的收集器
- 它进行收集时,必须暂停其它所有线程,直到它收集结束
- 可能会产生较长的停顿
- 参数:
-XX:+UseSerialGC
- 收集方式:
- 新生代、老年代均是串行回收
- 新生代采用复制算法
- 老年代采用标记-整理算法
并行(ParNew)收集器
- 多线程
- 其实就是Serial收集器的多线程版本
- 更加关注吞吐量
- 收集方式:
- 新生代采用复制算法
- 老年代采用标记-整理算法
-XX:+UseParallelGC
- 使用Parallel收集器 + 老年代串行
-XX:+UseParallelOldGC
- 使用Parallel收集器 + 老年代并行
-XX:MaxGCPauseMills
- 最大停顿时间,单位毫秒
- GC尽力保证回收时间不超过设定值
-XX:GCTimeRatio
- 0-100的取值范围
- 垃圾收集时间占总时间的比
- 默认99,即最大允许1%时间做GC
最后两个参数是矛盾的。因为停顿时间和吞吐量不可能同时调优
CMS(Concurrent Mark Sweep)收集器
- Concurrent Mark Sweep即并发标记清理(与用户线程一起执行)
- 以获取最短回收停顿时间为目标的收集器
- 从名字上可以看出CMS收集器是基于标记清除算法实现的:
- 初始标记(CMS initial mark)
- Step the world
- 根可以直接关联到的对象
- 速度快
- 并发标记(CMS concurrent mark)
- 和用户线程一起
- 主要标记过程,标记全部对象
- 重新标记(CMS remark)
- Step the world
- 由于并发标记时,用户线程依然运行,因此在正式清理前,再做修正
- 并发清除(CMS concurrent sweep)
- 和用户线程一起
- 基于标记结果,直接清理对象
- 初始标记(CMS initial mark)
缺点:
- 会影响系统整体吞吐量和性能
- 比如,在用户线程运行过程中,分一半线程去做GC,系统性能在GC阶段就会减半
- 清理不彻底
- 由于在清理阶段还运行着用户线程,会产生新的垃圾,无法清理
- 无法处理浮动垃圾,可能出现concurrent mode failure导致另一次GC发生
- 使用标记清除算法,会导致大量内存碎片
相关参数:
-XX:CMSInitiatingOccupancyFraction
- 设置触发GC的阈值,默认是老年代使用了68%触发
-XX:+ UseCMSCompactAtFullCollection
- Full GC后,进行一次整理
- 整理过程是独占的,会引起停顿时间变长
-XX:+CMSFullGCsBeforeCompaction
- 设置进行几次Full GC后,进行一次碎片整理
-XX:ParallelCMSThreads
- 设定CMS的线程数量
G1收集器
todo
参考:
- G1垃圾回收器介绍
- 周志明. 深入理解JVM虚拟机
- 详解 JVM Garbage First(G1) 垃圾收集器