门户网站改版建议,创新的福州网站建设,网站关闭申请书,百度联系电话多少一、并发标记与三色标记
问题#xff1a;三色标记到底发生在什么阶段#xff0c;替代了什么。并发标记
1、并发标记( Concurrent Marking)
从 GC Root 开始对堆中对象进行可达性分析#xff0c;递归扫描整个堆里的对象图#xff0c;找出要回收的对象#xff0c;这阶段耗…一、并发标记与三色标记
问题三色标记到底发生在什么阶段替代了什么。并发标记
1、并发标记( Concurrent Marking)
从 GC Root 开始对堆中对象进行可达性分析递归扫描整个堆里的对象图找出要回收的对象这阶段耗时较长但可与用户程序并发执行。当对象图扫描完成以后 并发标记时有引用变动的对象 这些对象会漏标。
CMS和G1的并发标记阶段使用的标记清除扫秒算法占用了太长中断时间所以用三色标记替换。
2、三色标记的概念多线程
在三色标记之前有一个算法叫Mark-And-Sweep标记清除。这个算法会给每一个对象设置一个标志位来记录对象是否被使用。最开始标识位都是0如果发现对象可达就会设置为1一步步下去就会呈现一个类似树状的结果。等标记的步骤完成后会将被标记的对象统一清理再次把所有的标记位置设置成0方便下次清理。
标记清除最大的问题是GC执行期间需要把整个程序完全暂停不能异步进行GC操作。因为不同阶段标记清除法的标志位0和1有不同的含义那么新增的对象无论标记成什么都有可能意外删除。对实时性要求高的系统来说这种需要长时间挂起的标记清除算法是不可接受的。所以就需要一个算法来解决GC运行时程序长时间挂起的问题那就是三色标记。
三色标记最大的好处就是异步从而可以以中断时间极少的代价或者完全没有中断来进行整个GC
三色标记把对象用三种颜色标记
黑色根对象或者这个对象及他的子对象都已经被扫描了灰色本身已经扫描了子对象还没扫描白色未被扫描的对象如果扫描完所有的对象之后最终白色的为不可达对象既为垃圾 3、三色标记的问题
GC并发情况下会有漏标的问题
第一步线程1完成所有的标记线程2还处于半完成状态 第二步引用发成变化B指向C变成A指向C 第三步线程1、2都完成所有的标记C对象是白色被错误的回收 4、三色标记并发情况下漏标记解决方案单线程最终标记
1cms的解决方案 incremental update 增量更新算法
CMS的三色标记发生并发标记和重新标记阶段
当一个白色对象被一个黑色对象引用将黑色对象重新标记为灰色让垃圾回收器重新扫描。增量更新关注的是引用新增。
2G1中的解决方案 STAB (snapshot-at-the-beginning) 快照处理算法
刚开始做一个快照当B指向C的引用消失的时候就把这个引用推到GC的堆栈保证C还能被GC扫描到最重要的是要把这个引用推到GC的堆栈是灰色对象B指向白色C的引用如果一旦某一个引用消失掉了会把它放到栈GC方法运行时数据也是来自栈中其实还是能找到它的下回直接扫描他就行了那样白色就不会漏标。再次做一个快照然后两个快照进行对比发现C不是垃圾那就要对C单独再做一次处理。
对应 G1 的垃圾回收过程中的最终标记
对用户线程做另外一个短暂的暂停用于处理并发阶段结束后仍遗留下来的最后那少量的SATB记录漏标对象
3incremental update与STAB对比
为什么CMS不用快照为什么G1不用增量
incremental Update算法关注引用的增加。A-C的引用如果增加了就变灰色需要重新扫描
SATB算法是关注引用的删除B-C的引用
G1 如果使用 Incremental Update 算法因为变成灰色的成员还要重新扫重新再来一遍效率太低了。
所以 G1 在处理并发标记的过程比 CMS 效率要高但是占内存高这个主要是解决漏标的算法决定的。
三、安全点与安全区域
1、安全点不会发生引用的变化的代码
用户线程暂停GC 线程要开始工作但是要确保用户线程暂停的这行字节码指令是不会导致引用关系的变化。
所以 JVM 会在字节码指令中选一些指令作为“安全点”比如方法调用、循环跳转、异常跳转等一般是这些指令才会产生安全点。
为什么它叫安全点GC 时要暂停业务线程并不是抢占式中断立马把业务线程中断而是主动式中断。主动式中断是设置一个标志这个标志是中断标志各业务线程在运行过程中会不停的主动去轮询这个标志一旦发现中断标志为 True就会在自己最近的“安全点”上主动中断挂起。
业务线程停止---安全点---垃圾回收线程开始
业务线程主动式中断GC开始STW业务线程 业务线程轮训标志S0 OR 1即GC开始标志主动去中断线程跑到最近的安全点挂起。 2、安全区域
为什么需要安全区域
要是业务线程都不执行业务线程处于 Sleep 或者是 Blocked 状态那么程序就没办法进入安全点对于这种情况就必须引入安全区域。
安全区域是指能够确保在某一段代码片段之中 引用关系不会发生变化因此在这个区域中任意地方开始垃圾收集都是安全的。我们也可以把安全区城看作被扩展拉伸了的安全点。 当用户线程执行到安全区域里面的代码时首先会标识自己已经进入了安全区域这段时间里 JVM 要发起 GC 就不必去管这个线程了。
当线程要离开安全区域时它要判断 JVM 是否已经完成了GC阶段根节点枚举或者其他 GC 中需要暂停用户线程的阶段)
1、如果完成了那线程就当作没事发生过继续执行。
2、否则它就必须一直等待 直到收到可以离开安全区域的信号为止。
四、低延迟的垃圾回收器
1、垃圾回收器的三项指标
传统的垃圾回收器一般情况下内存占用、吞吐量、延迟只能同时满足两个。但是现在的发展延迟这项的目标越来越重要。所以就有低延迟的垃圾回收器。
2、Eplison了解即可
这个垃圾回收器不能进行垃圾回收是一个“不干活”的垃圾回收器由 RedHat 推出它还要负责堆的管理与布局、对象的分配、与解释器的协作、与编译器的协作、与监控子系统协作等职责主要用于需要剥离垃圾收集器影响的性能测试和压力测试。
3、ZGC了解即可
有类似于 G1 的 Region但是没有分代。
标志性的设计是染色指针 ColoredPointers这个概念了解即可染色指针有 4TB 的内存限制但是效率极高它是一种将少量额外的信息存储在指针上的技术。
它可以做到几乎整个收集过程全程可并发短暂的 STW 也只与 GC Roots 大小相关而与堆空间内存大小无关因此可以实现任何堆空间 STW 的时间小于十毫秒的目标。
JDK11 –ZGC暂停时间不超过 10 毫秒且不会随着堆的增加而增加TB 级别的堆回收
有色指针、加载屏障。JDK12 支持并发类卸载进一步缩短暂停时间 JDK13(计划于 2019 年 9 月)将最大堆大小从 4TB 增加到 16TB
4、Shenandoah了解即可
第一款非 Oracle 公司开发的垃圾回收器有类似于 G1 的 Region但是没有分代。也用到了染色指针 ColoredPointers。效率没有 ZGC 高大概几十毫秒的目标。
五、GC 参数和GC 日志详解 1、GC 常用参数
-Xmn -Xms -Xmx –Xss 年轻代 最小堆 最大堆 栈空间
-XX:UseTLAB 使用 TLAB默认打开
-XX:PrintTLAB 打印 TLAB 的使用情况
-XX:TLABSize 设置 TLAB 大小
-XX:DisableExplicitGC 启用用于禁用对的调用处理的选项 System.gc()
-XX:PrintGC 查看 GC 基本信息
-XX:PrintGCDetails 查看 GC 详细信息
-XX:PrintHeapAtGC 每次一次 GC 后都打印堆信息
-XX:PrintGCTimeStamps 启用在每个 GC 上打印时间戳的功能
-XX:PrintGCApplicationConcurrentTime 打印应用程序时间(低)
-XX:PrintGCApplicationStoppedTime 打印暂停时长低
-XX:PrintReferenceGC 记录回收了多少种不同引用类型的引用重要性低
-verbose:class 类加载详细过程
-XX:PrintVMOptions 可在程序运行时打印虚拟机接受到的命令行显示参数
-XX:PrintFlagsFinal -XX:PrintFlagsInitial 打印所有的 JVM 参数、查看所有 JVM 参数启动的初始值必须会用
-XX:MaxTenuringThreshold 升代年龄最大值 15, 并行吞吐量收集器的默认值为 15而 CMS 收集器的默认值为 6。
2、Parallel 常用参数
-XX:SurvivorRatio 设置伊甸园空间大小与幸存者空间大小之间的比率。默认情况下此选项设置为 8
-XX:PreTenureSizeThreshold 大对象到底多大大于这个值的参数直接在老年代分配
-XX:MaxTenuringThreshold 升代年龄最大值 15, 并行吞吐量收集器的默认值为 15而 CMS 收集器的默认值为 6。
-XX:ParallelGCThreads 并行收集器的线程数同样适用于 CMS一般设为和 CPU 核数相同
-XX:UseAdaptiveSizePolicy 自动选择各区大小比例
3、CMS 常用参数
-XX:UseConcMarkSweepGC 启用 CMS 垃圾回收器
-XX:ParallelGCThreads 并行收集器的线程数同样适用于CMS一般设为和 CPU 核数相同
-XX:CMSInitiatingOccupancyFraction 使用多少比例的老年代后开始 CMS 收集默认是 68%(近似值)如果频繁发生 SerialOld 卡顿应该调小频繁 CMS 回收
-XX:UseCMSCompactAtFullCollection 在 FGC 时进行压缩
-XX:CMSFullGCsBeforeCompaction 多少次 FGC 之后进行压缩
-XX:CMSClassUnloadingEnabled 使用并发标记扫描CMS垃圾收集器时启用类卸载。默认情况下启用此选项。
-XX:CMSInitiatingPermOccupancyFraction 达到什么比例时进行 Perm 回收JDK 8 中不推荐使用此选项不能替代。
-XX:GCTimeRatio 设置 GC 时间占用程序运行时间的百分比不推荐使用
-XX:MaxGCPauseMillis 停顿时间是一个建议时间GC 会尝试用各种手段达到这个时间比如减小年轻代
4、G1 常用参数
-XX:UseG1GC 启用 CMS 垃圾收集器
-XX:MaxGCPauseMillis 设置最大 GC 暂停时间的目标以毫秒为单位。这是一个软目标并且 JVM 将尽最大的努力G1 会尝试调整 Young 区的块数来来实
现它。默认情况下没有最大暂停时间值。
-XX:GCPauseIntervalMillis GC 的间隔时间
-XX:G1HeapRegionSize 分区大小建议逐渐增大该值1 2 4 8 16 32。随着 size 增加垃圾的存活时间更长GC 间隔更长但每次 GC 的时间也会更长
-XX:G1NewSizePercent 新生代最小比例默认为 5%
-XX:G1MaxNewSizePercent 新生代最大比例默认为 60%
-XX:GCTimeRatioGC 时间建议比例G1 会根据这个值调整堆空间
-XX:ConcGCThreads 线程数量
-XX:InitiatingHeapOccupancyPercent 启动 G1 的堆空间占用比例根据整个堆的占用而触发并发 GC 周期