Day17 JVM垃圾收集
垃圾收集器与三色标记算法
- 垃圾收集算法
- 标记-清除 分为两个阶段,标记存活对象,然后统一回收未被标记的对象。但如果需要标记的对象太多的话效率不高,而且会产生大量不连续的碎片
- 标记-复制 为解决效率问题,引生了复制收集算法,将内存一分为二,平时只用一半,回收的时候把活着的对象移到另一半整齐排好,然后把原来的那一半直接清空。效率提高了,也没有空间碎片,但是每次都有一半的空间不使用,太浪费内存
- 标记-整理 根据老年代特点出的一种算法,老年代对象活得久,用复制算法得复制一大堆太慢,标记清除又有碎片。标记整理会先做标记,然后把活着的对象往一端推,最后把存活边界之外的内存清理掉
- 分代回收理论 基于对象生命周期假设的高效内存管理策略,核心思想是:大多数对象朝生暮死,只有少数对象会长期存活
- 垃圾收集器
- Serial收集器(-XX:+UseSerialGC -XX:UseSerialOldGC) 串行收集器是最基本、历史最悠久的收集器。单线程收集,收集过程中会停止其他所有的工作线程(Stop The World),直到它完成垃圾收集。 新生代采用复制算法,老年代使用标记-整理算法
- Parallel Scavenge收集器(-XX:+UseParallelGC -XX:UseParallelOldGC) 并行收集器,可以理解为Serial的多线程版本,除了是多线程收集外,其余行为与Serial无差异。Parallel Scavenge关注的是吞吐量,在于高效利用CPU,CMS等垃圾收集器关注的则是用户线程的停顿时间,提高用户体验。 新生代采用复制算法,老年代使用标记-整理算法
- ParNew收集器(-XX:UseParNewGC) 跟Parallel类似,区别是ParNew可以和CMS搭配使用,是大多数Server模式下虚拟机的首选 新生代采用复制算法
- CMS收集器(-XX:UseConcMarkSweepGC)
ConCurrent Mark Sweep收集器是一种以获取最短回收停顿时间为目标的收集器,适合在注重用户体验的应用上使用,采用标记-清除算法。
优点:并发收集,低停顿;缺点:对CPU资源敏感,无法清理浮动垃圾(用户线程和清理线程并行,也可能产生垃圾),标记-清除算法会产生大量空间碎片(通过参数-XX:UseCMSCompactAtFullCollection可以让jvm在执行完标记清除后再做整理),执行过程中存在不确定性,特别是在并发标记和并发清理阶段,一边回收一边运行,可能没回收完就再次触发了FullGC,也就是”concurrent mode failure”,此时会进入stop the world,用serial old垃圾收集器来回收
-
运行过程分为五步:
- 初始标记 暂停所有的其他线程(STW),并记录下gc roots直接能引用的对象,速度很快。
- 并发标记 并发标记阶段是从gc roots的直接关联对象开始遍历整个对象引用链,整个过程耗时较长,但是不会停止用户线程,可以与垃圾收集线程一起并发运行,此阶段因为用户程序还在继续运行,所以可能会有已标记过的对象状态发生改变
- 重新标记 为了修正并发标记期间因用户程序运行而导致标记状态变化的那一部分对象的标记记录(主要是处理漏标问题),这阶段处理停顿时间比初始标记阶段长,比并发标记阶段时间短。主要使用三色标记里的增量更新算法做重标
- 并发清理 开启用户线程,同时GC线程开始对未标记的区域做清扫,如果有新增对象会被标记为黑色不做任何处理(宁愿不清,不愿误清)
- 并发重置 重置本次GC过程中的标记数据

-
CMS的相关核心参数
- -XX:+UseConcMarkSweepGC:启用cms
- -XX:ConcGCThreads:并发的GC线程数
- -XX:+UseCMSCompactAtFullCollection:FullGC之后做压缩整理(减少碎片)
- -XX:CMSFullGCsBeforeCompaction:多少次FullGC之后压缩一次,默认是0,代表每次FullGC后都会压缩一次
- -XX:CMSInitiatingOccupancyFraction: 当老年代使用达到该比例时会触发FullGC(默认是92,这是百分比)
- -XX:+UseCMSInitiatingOccupancyOnly:只使用设定的回收阈值(-XX:CMSInitiatingOccupancyFraction设定的值),如果不指定,JVM仅在第一次使用设定值,后续则会自动调整
- -XX:+CMSScavengeBeforeRemark:用于在CMS垃圾收集器的重新标记阶段(Remark)之前,强制触发一次年轻代的垃圾回收。其目的是减少需要扫描的对象数量,从而缩短重新标记阶段的停顿时间。
- -XX:+CMSParallellnitialMarkEnabled:表示在初始标记的时候多线程执行,缩短STW
- -XX:+CMSParallelRemarkEnabled:在重新标记的时候多线程执行,缩短STW;
-
三色标记算法
在并发标记过程中,因为存在标记期间GC线程和应用线程并行的情况,期间对象的引用可能发生变化,多标和漏标就可能发生,因此引入了三色标记算法来解决此问题
三色标记算法是把GC Roots可达性分析遍历对象过程中遇到的所有对象按照“是否访问过”的条件标记成三种颜色:
- 黑色 表示对象已经被垃圾收集器访问过,且这个对象的所有引用都已经扫描过。
- 灰色 表示对象已经被垃圾收集器访问过,但这个对象上至少存在一个引用还未被扫描
- 白色 表示对象尚未被垃圾收集器访问过。可达性分析初始阶段,所有对象都是白色的,分析结束后如果还是白色对象,代表此对象不可达
-
评论
问答助学
相关内容
0个评论
全部评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论

