最早由Red Hat公司发起,目标是利用现代多核CPU的优势,减少大堆内存在GC时产生的停顿时间。随OpenJDK 12一起发布,暂停时间不依赖于堆的大小;这意味着无论堆的大小如何,暂停时间都是差不多的。
Shenandoah最初的目标是把GC停顿时间降到毫秒级,并且将对内存的支持扩展到太字节级别。为降低停顿时间,回收器需要使用更多的线程来并发处理回收任务,而要在降低停顿时间的同时能够支持更大的堆空间,回收器对CPU的多核处理能力提出更高的要求。
支持的特性:
System.gc()
Shenandoah GC策略
策略 | GC触发的条件 | GC选择回收分区的条件 |
---|---|---|
static | 当内存可用达到一定的國值之后,将启动GC | 在进行GC时,只选择垃圾超过一定阈值的分区 |
passive | 直到发生OOM,直接启动FGC | 在进行GC时,只选择垃圾超过一定阈值的分区,并且分区在转移后仍然能保留一定的预留空间 |
aggressive | 总是启动GC | 在进行GC时,只要分区有垃圾就会启动GC。判断分区是否有垃圾的条件:分区中垃圾超过一定的阈值;分区中可用的对象所占的空间小于一定的阈值 |
adaptive | 默认选项。当内存可用达到一定的阈值之后,或从上次GC到现在已经使用的内存超过一定阈值后,或根据使用的内存预测可用的内存不足以支撑到下一次GC时,将启动GC | 在进行GC时,只选择垃圾超过一定阈值的分区,并且分区在转移后仍然能保留一定的预留空间 |
compact | 当内存可用达到一定的阈值之后,或从上次GC到现在已经使用的内存超过一定阈值后,将启动GC | 在进行GC时,只选择垃圾超过一定阈值的分区,并且分区在转移后仍然能保留一定的预留空间。与自适应策略相比,它的阈值更低,回收的分区更多。 |
traversal | 启动遍历GC,是正常GC的优化版,把重定向和标记进行合并。GC触发时机和adaptive策略相同 | 回收的分区策略也和adaptive策略相同 |
GC策略决定Shenandoah何时启动GC以及在GC时回收哪些分区。
Shenandoah为了更好地管理内存,实现4类GC算法:
降级回收算法和并行FGC类似,都是在STW中进行的。它和FGC最大的区别就是降级回收会重用当前已经并发执行的标记、转移或者重定位的信息,从当前GC失败的地方继续向下执行。
Shenandoah中正常回收有两种模式:一般模式和优化模式。区别在于是否在标记时执行重定位,在标记的过程中执行重定位,则称为优化模式,否则称为一般模式。可通过参数ShenandoahUpdateRefsEarly
控制,可能值为off/false,表示GC执行优化模式;on/true/adaptive,表示执行一般模式。
一般模式GC步骤:
整个GC活动图:
优化模式GC的步骤:
Shenandoah中的优化模式和ZGC的GC过程基本类似,把标记阶段和重定位阶段合并。正常回收在运行的过程中,应用程序和GC线程都可能需要分配内存空间,也都有可能遇到内存不足导致分配失败的情况,此时正常回收将进入降级回收状态,如果在降级回收时再遇到内存不足,将进入FGC状态。
正常回收、降级回收和FGC交互图:
Shenandoah遍历回收就是把并发标记、并发转移和并发重定位合并到一个阶段。
Shenandoah遍历回收的步骤:
遍历回收算法,思路简单但实现复杂。需要解决两个问题:
Shenandoah中解决一致性问题的方法到也比较简单。通过执行顺序的不同来保证一致性。具体来说在标记时,如果对象需要更新引用,则先更新引用,如果没有引用更新,则判断是否需要转移,如果需要转移则转移,最后才能标记对象。
G1、ZGC和Shenandoah的异同点
对比项 | G1 | ZGC | Shenandoah GC |
---|---|---|---|
内存连续性 | 堆内存基于分区实现,最小分区为1MB,最大分区可达32MB | 基于分页设计,类似于G1分区。页面有3种类型,2MB、32MB和N*MB | 基于分区理论实现,最小分区为256KB,最大分区可为32MB |
是否支持分代 | 支持 | 不支持 | 不支持 |
是否全量回收 | 新生代分区在 YGC/MixedGC/FGC 中会被全部回收老生代在 Mixed GC 时部分回收,在 FGC 时全部回收 | 部分页面回收 | 部分分区回收 |
屏障 | 支持读屏障和写屏障,读屏障是为了正确标记对象,写屏障是为了处理代际引用关系管理(G1中有单独的线程处理代际引用) | 仅需要支持读屏障即可实现并发标记、并发转移和并发重定位 | 支持读屏障和写屏障,读屏障是为了对象正确标记和并发处理读数据写屏障是为了并发处理同时写数据、实际上Shenandoah还需要支持比较屏障(比较屏障是通过两个读屏障实现的) |
GC时并发性 | 目前只支持并发标记 | 支持并发标记、并发转移和并发重定位 | 支持并发标记、并发转移和并发重定位 |
GC触发策略 | 使用衰减停顿模型预测是否启动GC | 提供多种触发GC的规则,其中最为常见的触发方式是根据正态分布预测的内存分配的情况触发 | 提供多种触发GC的策略:static、passive、aggressive、compactadaptive |
NUMA支持 | 尚未支持,提案JEP 345为G1支持NUMA | 支持 | 不支持 |
字符串去重 | 支持 | 不支持 | 支持 |
引用处理 | 并行处理 | 并发处理 | 并行处理 |
在GC时非常类似,都实现并发垃圾标记、并发转移、并发重定位、压缩堆空间。Shenandoah更加类似于G1,把G1中的并行转移变成并发转移。
ZGC并发的基础是地址多视图映射。
Shenandoah并发的基础是在对象头增加一个额外数据Brook pointer,在实现读写屏障时通过Brook pointer访问对象。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。